c# - 如何在 Unity Editor 脚本中将 Persistent Listener 添加到 Button.onClick 事件

标签 c# unity3d

我正在尝试做一件简单的事情:

  1. 创建一个新的GameObject
  2. Button 组件添加到 GameObject
  3. ButtonOnClick 事件添加持久监听器。

我尝试注册的方法在其他一些脚本中。这是我正在尝试的一段代码:

MyScript myScriptInstance = FindObjectOfType<MyScript>(); 
var go = new GameObject();
var btn = go.AddComponent<Button>();
    
var targetinfo = UnityEvent.GetValidMethodInfo(myScriptInstance,
"OnButtonClick", new Type[]{typeof(GameObject)});

var action = (UnityAction) Delegate.CreateDelegate(typeof(UnityAction),go, targetinfo, false);
UnityEventTools.AddPersistentListener(btn.onClick, action);

MyScript.cs 看起来像这样:

public class MyScript : MonoBehaviour
{
    public void OnButtonClick(GameObject sender)
    {
        // do some stuff here.
    }
}

当我运行这段代码时,Buttons Onclick 监听器是空的,如下所示:

enter image description here

如果我换行

var action = (UnityAction) Delegate.CreateDelegate(typeof(UnityAction),
go, targetinfo, false);

var action = (UnityAction) Delegate.CreateDelegate(typeof(UnityAction),
go, targetinfo, true);

我明白了:

ArgumentException: method argument length mismatch System.Delegate.CreateDelegate (System.Type type, System.Object firstArgument, System.Reflection.MethodInfo method, Boolean throwOnBindFailure)

我关注了these instructions但不知道这里出了什么问题。

非常感谢任何形式的帮助。

最佳答案

在这上面花了这么多时间之后,我得出结论,这是一个错误。这是一个单声道错误。

引用资料如下:

Ref 1 , Ref 2 , Ref 3Ref 4

Unity 不会很快解决这个问题。他们通常不会修复与 Mono 相关的问题,因为他们已经在努力升级到最新的 Mono 运行时。

幸运的是,还有另外两种解决方法:

  1. AddObjectPersistentListenerUnityAction 与通用参数一起使用,然后将通用参数传递给 Delegate.CreateDelegate 函数。

    MyScript myScriptInstance = FindObjectOfType<MyScript>();
    var go = new GameObject();
    var btn = go.AddComponent<Button>();
    
    var targetinfo = UnityEvent.GetValidMethodInfo(myScriptInstance,
        "OnButtonClick", new Type[] { typeof(GameObject) });
    
    UnityAction<GameObject> action = Delegate.CreateDelegate(typeof(UnityAction<GameObject>), myScriptInstance, targetinfo, false) as UnityAction<GameObject>;
    
    UnityEventTools.AddObjectPersistentListener<GameObject>(btn.onClick, action, go);
    
  2. 根本不要使用 Delegate.CreateDelegate。只需使用 AddObjectPersistentListener

    MyScript myScriptInstance = FindObjectOfType<MyScript>();
    var go = new GameObject();
    var btn = go.AddComponent<Button>();
    
    UnityAction<GameObject> action = new UnityAction<GameObject>(myScriptInstance.OnButtonClick);
    UnityEventTools.AddObjectPersistentListener<GameObject>(btn.onClick, action, go);
    

这两个都给你这个:

enter image description here

第二种方案不需要用反射找函数。您必须在运行时之前绑定(bind)函数。第一个使用反射。

您可能需要使用第一个解决方案,因为它与您正在做的非常相似,并且您可以提供函数名称作为字符串变量。

关于c# - 如何在 Unity Editor 脚本中将 Persistent Listener 添加到 Button.onClick 事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40655089/

相关文章:

c# - 将 Rx 超时与 FromEventPattern Observer 结合使用

c# - FIX 阅读重复组

c# - 打字时如何设置 VSCode 以在 C# 和 C++ 中的新行上放置花括号?

c# - 通过 CLI 从 Unity 生成 Visual Studio 项目

unity3d - 通过 Unity 中的 Oculus 应用程序登录 Google 和 Facebook

c# - 相交未给出预期结果

c# - Visual Studio 找不到符号,虽然类在目录中,但它没有出现在解决方案资源管理器中

c# - Xamarin.Forms 在文件系统中保存文件

mono - 让 MonoDevelop 尊重 smcs.rsp

c# - 在构建到 UWP 和 Il2CPP 之后,通用方法中的 AOT(提前)出现问题