C# 如何在Unity中维护运行时对对象实例化的引用
我需要在运行时实例化一个对象,其中对象的数量基于txt文件(行数)。所有对象都需要可单击(onClick()事件),当按下它们时,必须显示工具提示。工具提示是特定的(Object1->Tooltip1,Object2->Tooltip2)。工具提示只是一个面板,它们包含在其他一些面板和按钮中。其中之一将创建一个新面板。这些面板也是特定的(工具提示1->Panel1等等)。我为三个对象中的每一个创建一个预置 因此,Object1-onClick()->Tooltip1-onClick()->Panel1。在运行时 如何在运行时保留对象创建的引用 我的第一个解决方案:C# 如何在Unity中维护运行时对对象实例化的引用,c#,unity3d,reference,C#,Unity3d,Reference,我需要在运行时实例化一个对象,其中对象的数量基于txt文件(行数)。所有对象都需要可单击(onClick()事件),当按下它们时,必须显示工具提示。工具提示是特定的(Object1->Tooltip1,Object2->Tooltip2)。工具提示只是一个面板,它们包含在其他一些面板和按钮中。其中之一将创建一个新面板。这些面板也是特定的(工具提示1->Panel1等等)。我为三个对象中的每一个创建一个预置 因此,Object1-onClick()->Tooltip1-onClick()->Pan
for (int i = 0; i < numberOfObject; i++)
{
var instance = Instantiate(m_ObjectPrefab);
instance.name = "Object_" + m_nameObject[i];
var instancePanel = Instantiate(m_panelPrefab, m_canvas.transform);
instancePanel.name = "Panel_" + m_nameObject[i];
instancePanel.SetActive(false);
instancePanelTooltip.SetActive(false);
DetectClickOnObject scriptDetectClickPanelTooltip = instance.AddComponent<DetectClickOnObject>();
scriptDetectClickPanelTooltip.SetTooltip(instancePanelTooltip);
作为数据管理员
public class POIManager : MonoBehaviour
{
List<DataModelPOI> dataCollectionPOI = new List<DataModelPOI>();
void Start()
{
ReadFile();
SpawnPOI();
}
void Update()
{
int count = dataCollectionPOI.Count;
for (int i = 0; i < count; i++)
{
UpdatePOIPosition();
}
}
void ReadFile()
{
TakeDataFromFile();
for (int i = 0; i < ength; i++)
{
DataModelPOI dataPOI = new DataModelPOI(m_namePoi[i], m_namePoi[i], _locations[i]);
dataCollectionPOI.Add(dataPOI);
}
}
private void SpawnPOI()
{
for (int i = 0; i < dataCollectionPOI.Count; i++)
{
DataModelPOI dataPOI = dataCollectionPOI[i];
var instance = Instantiate(m_POIPrefab);
instance.name = "POI_" + m_namePoi[i];
dataPOI.m_gameObject_POI = instance;
dataPOI.m_gameObjectTooltip = m_panelTooltipPOI;
dataPOI.m_gameObjectPanel = m_panelPOI;
}
}
公共类POIManager:MonoBehavior
{
List dataCollectionPOI=新列表();
void Start()
{
ReadFile();
SpawnPOI();
}
无效更新()
{
int count=数据采集点计数;
for(int i=0;i
现在我需要在之前注册与GameObject实例化相关的事件。我想在我的EventManager中注册。如何在DataManager中创建并提供的EventManager类中指向
dataCollectionPOI
?感谢您的时间。根据我的理解,您的问题主要是一个设计问题。在本答案的第一部分,我我给你一个设计建议,并保留对对象的引用。在第二部分中,我将给你一些有关性能的提示
[我使用RootObject而不是Object来指代您创建的主要游戏对象。]
设计
让我们把我们的需求细分,然后针对每一个需求提出一个解决方案
首先我们要读取一些文本文件,然后从中获取一些数据。这些数据将在以后用于创建游戏对象。现在让我们只关注数据本身
这里我们需要的是一个manager类,它为我们读取文件并以某种形式存储数据。我们稍后访问此manager并请求我们的数据以创建游戏对象
此管理器类将我们的数据存储在一组数据对象中[注意,这里我们讨论的是普通对象,而不是Unity的游戏对象]。您需要根据您拥有的每行文本设计此数据类。或者,您也可以在此处保留对游戏对象的引用
假设您正在从每行读取三个字符串值,分别命名为ValueOne
、ValueTwo
和valuetwree
,并且希望保留对三个名为RootObject
、ToolTip
和Panel
的游戏对象的引用。为此,您可以定义以下类:
public class DataModel {
// Values read from text file.
public string valueOne { get; private set; }
public string valueTwo { get; private set; }
public string valueThree { get; private set; }
// Placeholders for GameObjecs created at runtime.
public GameObject rootObject;
public GameObject tooltipObject;
public GameObject panelObject;
public DataModel(string valueOne, string valueTwo, string valueThree){
this.valueOne = valueOne;
this.valueTwo = valueTwo;
this.valueThree = valueThree;
}
}
然后,在manager类中,您可以创建一个用于保存数据的集合(例如列表)。manager类应该在某个时候读取文本文件,并使用DataModel实例填充此列表。它将类似于:
public class DataManager {
List<DataModel> dataCollection = new List<DataModel>();
public void ReadFile() {
// Here you need to read the file and get the values you need.
// The actual code should be different from what I'm putting here.
foreach(string line in lines) {
// You get valueOne, valueTwo and valueThree
// from each line and maybe prepare them
// (maybe you need conversion from string to int)
DataModel data = new DataModel(valueOne, valueTwo, valueThree);
dataCollection.Add(data);
}
}
}
公共类数据管理器{
列表数据收集=新列表();
公共void ReadFile(){
//在这里,您需要读取文件并获得所需的值。
//实际的代码应该与我在这里放的不同。
foreach(行中的字符串行){
//你得到了valueOne,valueTwo和valueThree
//从每一行开始,也许准备它们
//(可能需要将字符串转换为int)
数据模型数据=新数据模型(值一、值二、值三);
数据收集。添加(数据);
}
}
}
在调用manager上的方法读取数据后,您可以随时准备好数据
现在是基于数据创建对象并保存引用的时候了
for (int i = 0; i++; i <= manager.dataCollection.Count) {
DataModel data = manager.dataCollection[i];
data.rootObject = instantiate() // You instantiate the root GameObject here.
data.tooltip = instantiate() // You instantiate the tooltop GameObject here.
data.panel = instantiate() // You instantiate the panel GameObject here.
}
for(int i=0;i++;i您基本上走在正确的轨道上,但您可以分离(或“对象化”)哪些脚本保留哪些引用。将管理预置内部工作的脚本保留在这些预置中
工具提示使用类似于单例的模式是绝对可行的。对于无法使用单例的情况,例如在可单击对象中,请使用更类似于依赖项注入的方式(保存在查找中)和预存储引用:
var obj = Instantiate(...);
obj.GetComponent<SomeManagerScript>.SomeDependency = SingletonInstance;
obj.GetComponent<StoredReferenceScript>.TextPanel.Text = "Some Text";
var obj=实例化(…);
obj.GetComponent.SomeDependency=singleStation;
obj.GetComponent.TextPanel.Text=“一些文本”;
对于事件,您可以通过两种方式来处理它们。一种是,每个clickable管理自己的绑定/功能;另一种是,每个clickable通知全局管理器它已被单击,并且管理器确定要采取的操作。基本上,您需要在运行时创建一个对象,并为该特定对象设置数据
下面是最简单的方法
首先创建脚本,第一个脚本可以在运行时创建对象,第二个脚本是与预置一起附加的数据设置脚本
因此,当您在运行时创建对象时,您可以选择
public class DataManager {
List<DataModel> dataCollection = new List<DataModel>();
public void ReadFile() {
// Here you need to read the file and get the values you need.
// The actual code should be different from what I'm putting here.
foreach(string line in lines) {
// You get valueOne, valueTwo and valueThree
// from each line and maybe prepare them
// (maybe you need conversion from string to int)
DataModel data = new DataModel(valueOne, valueTwo, valueThree);
dataCollection.Add(data);
}
}
}
for (int i = 0; i++; i <= manager.dataCollection.Count) {
DataModel data = manager.dataCollection[i];
data.rootObject = instantiate() // You instantiate the root GameObject here.
data.tooltip = instantiate() // You instantiate the tooltop GameObject here.
data.panel = instantiate() // You instantiate the panel GameObject here.
}
var obj = Instantiate(...);
obj.GetComponent<SomeManagerScript>.SomeDependency = SingletonInstance;
obj.GetComponent<StoredReferenceScript>.TextPanel.Text = "Some Text";
GameObject object = Instantiate(gameObject,parent)
DataSetter s = object.GetComponent<DataSetter>().toolTip = "YourTooltip";