Unity - 当按钮被销毁时onClick的监听器被破坏了吗?

Mr *_*ons 1 c# unity-game-engine

我正在实例化许多按钮,当点击时需要调用一个函数(通过监听器).但我也经常摧毁它们.这些听众是否也被销毁或者我是否需要删除它们?

例:

public void makeButton()
{
    GameObject spawnedButton = Instantiate(prefabButton, prefabButton.transform.position, prefabButton.transform.rotation) as GameObject;   

    spawnedButton.GetComponent<Button>().onClick.AddListener(()=>
    {
        listedButtonClicked(someOtherObjectThatWillNotBeDeleted, spawnedButton);
    });
}

public void listedButtonClicked(GameObject target, GameObject button)
{
    Debug.Log(target);
    Debug.Log(button);
}
Run Code Online (Sandbox Code Playgroud)

......所以什么时候spawnedButton被摧毁,这个听众会留下来吗?我正在实例化并删除大量按钮,因此它可能与我相关.

Eve*_*rts 6

好的,这会有点深入.

考虑一下:

Button button;
void Start()
{
     button.onClick.AddListener(Method);
}
void Method()
{
    print("Hey");
}
Run Code Online (Sandbox Code Playgroud)

这很好,你的Button组件获得了一个方法的"链接",所以当触发onClick时,它会跳转到Method的地址并从那里运行代码.

第二种情况:

Button button;
void Start()
{
     button.onClick.AddListener(Method);
     Destroy(this);
}
void Method()
{
    print("Hey");
}
Run Code Online (Sandbox Code Playgroud)

注意我销毁当前组件,运行它并触发onClick并且没有问题(?? !!),它打印正常.

第三种情况:

Button button;
string str = "Hey there";
void Start()
{
     button.onClick.AddListener(Method);
     Destroy(this);
}
void Method()
{
    print(this.str);
} 
Run Code Online (Sandbox Code Playgroud)

它崩溃了.现在来解释一下.方法总是静态的,编译器(或创建者)足够聪明,可以认为每个实例都不需要拥有自己的方法,而是拥有实例可以自己传递的共享方法模板.

方法如下:

  void ClassName.MethodName(this ClassName); 
Run Code Online (Sandbox Code Playgroud)

使用实例调用时,此参数将移至前面,并且是非强制性的.该参数实际上可以在方法中使用,因为您可以使用它.同样,它不是强制性的.

因此,在第一种情况下,它可以工作,虽然脚本不再存在,这是因为没有使用任何实例成员.在最后一个示例中,使用了str,并且由于该对象不再存在,因此它会抛出空引用异常.

考虑到另一种方式.

如果创建脚本仍然存在且Button游戏对象或组件被销毁,那么您根本没有风险.清除onClick事件会更明智,但因为它会被破坏,反之亦然.你的产生者在创建所有按钮的循环的下一次迭代中失去了对Button的任何知识:

for(i=0;i<10;i++)
{
    GameObject go = null; // new reference added on method stack
    go = Instantiate<GameObject>(btnPrefab); // new instance added to reference
} // go connection is lost right here, a new go added to stack in next iteration
Run Code Online (Sandbox Code Playgroud)