Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/285.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/unity3d/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在Unity中维护运行时对对象实例化的引用_C#_Unity3d_Reference - Fatal编程技术网

C# 如何在Unity中维护运行时对对象实例化的引用

C# 如何在Unity中维护运行时对对象实例化的引用,c#,unity3d,reference,C#,Unity3d,Reference,我需要在运行时实例化一个对象,其中对象的数量基于txt文件(行数)。所有对象都需要可单击(onClick()事件),当按下它们时,必须显示工具提示。工具提示是特定的(Object1->Tooltip1,Object2->Tooltip2)。工具提示只是一个面板,它们包含在其他一些面板和按钮中。其中之一将创建一个新面板。这些面板也是特定的(工具提示1->Panel1等等)。我为三个对象中的每一个创建一个预置 因此,Object1-onClick()->Tooltip1-onClick()->Pan

我需要在运行时实例化一个对象,其中对象的数量基于txt文件(行数)。所有对象都需要可单击(onClick()事件),当按下它们时,必须显示工具提示。工具提示是特定的(Object1->Tooltip1,Object2->Tooltip2)。工具提示只是一个面板,它们包含在其他一些面板和按钮中。其中之一将创建一个新面板。这些面板也是特定的(工具提示1->Panel1等等)。我为三个对象中的每一个创建一个预置

因此,Object1-onClick()->Tooltip1-onClick()->Panel1。在运行时

如何在运行时保留对象创建的引用

我的第一个解决方案

  • 创建一个空对象,并使用公共变量(对象预置)为其分配一个脚本
  • 实例化对象预制:

    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";