我想做一件简单的事情:
GameObject
Button
组件。 我尝试注册的方法是在其他一些脚本中。这是我正在尝试的一段代码:
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.
}
}
当我运行此代码时,按钮Onclick监听器是空的,如下所示:
如果我改变了行
var action = (UnityAction) Delegate.CreateDelegate(typeof(UnityAction),
go, targetinfo, false);
到
var action = (UnityAction) Delegate.CreateDelegate(typeof(UnityAction),
go, targetinfo, true);
我明白了:
ArgumentException:方法参数长度不匹配 System.Delegate.CreateDelegate(System.Type类型,System.Object firstArgument,System.Reflection.MethodInfo方法,布尔值 throwOnBindFailure)
我跟着these instructions,但不知道这里出了什么问题。
真正感谢任何形式的帮助。
答案 0 :(得分:4)
花了这么多时间后,我得出结论,这是一个错误。这是一个单声道的bug。
以下是参考资料:
Unity不会很快解决这个问题。他们通常不会修复与Mono相关的内容,因为他们已经在努力升级到最新的Mono运行时。
幸运的是,还有另外两种解决方法:
1 。使用通用参数AddObjectPersistentListener
和UnityAction
,然后将通用内容传递给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);
如果这些都给你这个:
第二种解决方案不需要使用反射来查找函数。您必须在运行时绑定该函数。第一个使用反射。
您可能需要使用第一个解决方案,因为它与您正在执行的操作非常相似,您可以将函数名称作为字符串变量提供。
答案 1 :(得分:0)
也许我没有理解你的问题,但是Button脚本公开了onClick事件,你可以add listeners to(在代码中)。
这是我使用的代码:
// Use this for initialization
void Start () {
MyScript myScriptInstance = FindObjectOfType<MyScript> ();
GameObject go = DefaultControls.CreateButton (new DefaultControls.Resources());
var btn = go.GetComponent<Button> ();
btn.onClick.AddListener (myScriptInstance.TestMethod);
}
这里是MyScript.TestMethod的代码:
public void TestMethod ()
{
Debug.Log ("TestMethod");
}
有几点需要注意:
答案 2 :(得分:-1)
因为我无法发表评论,非常感谢@Programmer的回答! 我在第二个示例中编辑了您的代码,以在编辑器中也填充UnityEvents。 将代码复制并粘贴到2个单独的脚本中,一个名为Menu,一个名为MyScript。 确保“菜单”脚本位于名为“编辑器”的文件夹中。
%timeit