【发布时间】:2019-04-17 00:06:13
【问题描述】:
我需要在运行时实例化一个对象,其中对象的数量基于一个 txt 文件(行数)。所有对象都必须是可点击的(onClick() 事件),并且当它们被按下时,必须出现工具提示。工具提示是特定的(Object1 -> Tooltip1,Object2 -> Tooltip2)。工具提示只是一个面板,它们包含在其他一些面板和按钮中。其中之一创建一个新面板。这些面板也是特定的(Tooltip1 -> Panel1 等等)。我为三个对象中的每一个创建了一个预制件。
所以,Object1 - onClick() -> Tooltip1 - onClick() -> Panel1。在运行时。
如何保持在运行时创建的对象的引用?
我的第一个解决方案:
- 创建一个 Empty 对象并使用公共变量(Object prefab)为其分配一个脚本。
-
实例化对象预制件:
for (int i = 0; i < numberOfObject; i++) { var instance = Instantiate(m_ObjectPrefab); instance.name = "Object_" + m_nameObject[i]; -
为每个对象实例化一个工具提示:
var instancePanelTooltip = Instantiate(m_panelTooltipPrefab, m_canvas.transform); instancePanelTooltip.name = "Panel_Tooltip_" + 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); -
为 Tooltip 上的按钮添加事件处理程序
DetectClickOnObject scriptDetectClickPanel = buttonOpenPanel.AddComponent<DetectClickOnObject>(); scriptDetectClickPanel.SetPanel(instancePanel); }
此解决方案的问题:
我将为文件的每一行实例化 3 个对象(对象、工具提示、面板)。 Object 可以,但 Tooltip 和 Panel 不行,因为只有一个 Tooltip 处于活动状态(Panel 也一样)。
我只是避免了引用问题,因为我在同一个地方创建了所有对象(每个元素一个),但是如果我需要在没有引用的情况下访问 Tooltip2 或 Panel3(我是尽量避免 Find 和类似的)。
第一个解决方案的结论:解决方案有效,但我认为有更好的方法(避免创建太多对象并以正确的方式保持引用)。
我的第二个解决方案(指南):
- 我正在尝试创建一个类来保持对所有在运行时创建的对象的引用。
- 我想为每一行创建一个对象实例,但我只需要一个工具提示和面板用于所有对象,并根据单击的对象更改属性。所以 Object 是在运行时创建的,但 Tooltip 和 Panel 已经在场景中但没有激活。
- 我需要一个注册事件管理器来在运行时在对象上添加 onClick() 事件,并且它需要根据单击的对象处理要在工具提示和面板上设置的属性。
第二种解决方案的问题: 参考 1)我尝试关注 that,但最终一无所获。我在单身,静态和其他东西之间迷失了。参考2)我认为这很容易,我只需要删除一些第一个解决方案。参考 3) 如果我没有类参考管理器,我将无能为力。
我在寻找什么:
- 第一个解决方案这么糟糕吗?如果我看代码我很反感,它与优雅(或类似的东西)相去甚远。
- 您能否建议我如何使用参考管理器在运行时跟踪参考创建?以及如何使用?
@Behnam Sattar 建议: 作为 DataModell 类,
public class DataModelPOI
{
public string m_namePOI { get; private set; }
public string m_locationPOI { get; private set; }
public Vector2d m_positionPOI { get; private set; }
public GameObject m_gameObject_POI;
public GameObject m_gameObjectTooltip;
public GameObject m_gameObjectPanel;
public DataModelPOI(string namePOI, string locationPOI, Vector2d positionPOI)
{
this.m_namePOI = namePOI;
this.m_locationPOI = locationPOI;
this.m_positionPOI = positionPOI;
}
}
作为数据管理员,
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;
}
}
现在我需要先注册 Event 关联到 GameObject 实例化。我想在我的 EventManager 中这样做。如何在 DataManager 中创建和提供的 EventManager 类中指向 dataCollectionPOI?感谢您的宝贵时间。
【问题讨论】: