使用 Instantiate() 克隆对象会丢失侦听器

Cloning an object with Instantiate() loses the listeners

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

可以通过 Canvas 和一个按钮并附加此脚本来测试该行为:

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 以便它保留事件侦听器?

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

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

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

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

至于AddListener

  • 这个函数添加了一个"non persistent"委托,这意味着它不会出现在检查器中,当你在编辑器中退出播放模式时会被遗忘。这些不同于 "persistent" 听众,您可以在 edit-time 期间在检查器中添加,并且在编辑和播放模式之间持续存在。

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

出于这些原因,我假设 non-persistent 没有序列化,然后没有传递给克隆的 object。