【问题标题】:Cloning an object with Instantiate() loses the listeners使用 Instantiate() 克隆对象会丢失侦听器
【发布时间】:2016-11-14 13:34:21
【问题描述】:

在运行时使用 Instantiate() 克隆按钮时,该按钮在其 onClick 事件中包含侦听器,克隆中不存在侦听器。

可以通过带有按钮的画布和附加的脚本来测试行为:

void Start () {
    var button = transform.GetChild (0);
    button.GetComponent<Button> ().onClick.AddListener (new UnityAction(() => Debug.Log("Event triggered!")));
    var button2 = Instantiate (button);
    button2.SetParent (transform);
}

克隆的按钮在单击时不会向控制台打印任何内容。 有没有办法克隆 GameObject 以便它保留事件侦听器?

【问题讨论】:

  • 嗨 Felk - 这是正确且明显的行为。我看不出它如何以其他方式工作。它在AddListener doco 中说得对。我想,您可以编写一个扩展 (intro for any new programmers reading) 来实例化并复制它们。
  • 对吗?大概。明显的?不。它确实没有在文档中这么说:This function adds a "non persistent" delegate, which means it will not show up in the inspector, and will be forgotten when you exit play mode in the editor.
  • 很公平,你的问题很好,因为它会帮助很多人。我只想说,(对我来说不幸)经常使用 Unity(而不是说,躺在海滩上)这是“它唯一可以工作的明显方式”。我希望这是有道理的。如果在你实例化它时保持它的连接,那将是非常奇怪的;我的意思是,这只是整个系统中一个令人震惊的奇怪功能!我什至无法想象使用它。我的意思是,在你真正做最简单的事情(即“制作任何游戏对象”)之前,你必须编写一套代码来......
  • ...否定该功能,你知道的!呵!同样,很容易添加带有一行代码的扩展来执行您在特定情况下所说的操作。 (也只是出于好奇,很难看到很多用例;另一个具有相同功能的按钮。)
  • 我的用例只是一个工厂,它生产一些“原始”小部件,这些小部件显示在多个位置(克隆),但它们的点击行为应该相同。

标签: button unity3d listener clone


【解决方案1】:

运行时侦听器不是持久的,也不是序列化的。因此,当您克隆按钮时,它们不会被传递。

您要么必须将方法添加到脚本并将脚本附加到您的预制件上,以便它被序列化,要么像第一个一样通过代码分配它。

  • 实例化。当您在预制件上调用 Instantiate() 或 存在于场景中的游戏对象,或其他任何东西 问题(从 UnityEngine.Object 派生的所有内容都可以是 序列化),我们序列化对象,然后创建一个新对象,然后 然后我们将数据“反序列化”到新对象上。 (然后我们运行 在不同的变体中再次使用相同的序列化代码,我们在其中使用它 报告引用了哪些其他 UnityEngine.Object。我们 然后检查所有引用的 UnityEngine.Object 是否属于它们 正在实例化()的数据。如果参考指向 一些“外部”的东西(比如纹理),我们保留它的引用 是,如果它指向“内部”的东西(比如一个孩子 游戏对象),我们修补对应副本的引用)。

http://blogs.unity3d.com/2014/06/24/serialization-in-unity/

至于 AddListener

  • 此函数添加了一个“非持久”委托,这意味着它不会显示在检查器中,并且在您退出编辑器中的播放模式时会被遗忘。这些不同于“持久”侦听器,您可以在编辑期间在检查器中添加,并且在编辑和播放模式之间持续存在。

https://docs.unity3d.com/ScriptReference/Events.UnityEvent.AddListener.html

出于这些原因,我假设非持久性未序列化,然后未传递给克隆对象。

【讨论】:

  • 由于文档页面没有说明,这是否意味着Instantiate() 通过序列化和反序列化克隆,而侦听器是瞬态的?
  • 谢谢。我通过在要克隆的对象上放置一个自定义脚本来使其工作,然后将侦听器添加到Start()
猜你喜欢
  • 1970-01-01
  • 2016-12-04
  • 1970-01-01
  • 2018-04-20
  • 1970-01-01
  • 2012-04-26
  • 2014-12-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多