首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在Unity脚本中向Button.onClick事件添加持久侦听器

如何在Unity脚本中向Button.onClick事件添加持久侦听器
EN

Stack Overflow用户
提问于 2016-11-17 12:37:14
回答 3查看 15.1K关注 0票数 12

我试着做一件简单的事情:

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

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

代码语言:javascript
运行
复制
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看起来是这样的:

代码语言:javascript
运行
复制
public class MyScript : MonoBehaviour
{
    public void OnButtonClick(GameObject sender)
    {
        // do some stuff here.
    }
}

运行此代码时,Onclick侦听器按钮为空,如下所示:

如果我改变了路线

代码语言:javascript
运行
复制
var action = (UnityAction) Delegate.CreateDelegate(typeof(UnityAction),
go, targetinfo, false);

代码语言:javascript
运行
复制
var action = (UnityAction) Delegate.CreateDelegate(typeof(UnityAction),
go, targetinfo, true);

我得到:

ArgumentException:方法参数长度不匹配System.Delegate.CreateDelegate (System.Type类型,System.Object firstArgument,System.Reflection.MethodInfo方法,布尔throwOnBindFailure)

我跟踪了这些指示,但不知道这里出了什么问题。

任何形式的帮助都是值得感激的。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-12-07 21:16:47

在花了这么多时间在这个问题上,我得出结论,这是一个错误。这是一个Mono虫。

以下是参考资料:

参1参2参3参4

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

幸运的是,还有两种解决办法:

  1. 使用带有泛型参数的AddObjectPersistentListenerUnityAction,然后将泛型传递给Delegate.CreateDelegate函数。 UnityEvent.GetValidMethodInfo(myScriptInstance,myScriptInstance = FindObjectOfType();var go =新GameObject();var btn = go.AddComponent();var myScriptInstance= MyScript "OnButtonClick",new Type[] { typeof(GameObject) };UnityAction action = Delegate.CreateDelegate(typeof(UnityAction),myScriptInstance,targetinfo,false)为UnityAction;
  2. 完全不要使用Delegate.CreateDelegate .只需使用AddObjectPersistentListener。 UnityEventTools.AddObjectPersistentListener(btn.onClick,MyScript myScriptInstance = FindObjectOfType();var go =新GameObject();var btn = go.AddComponent();UnityAction action =新UnityAction(myScriptInstance.OnButtonClick);

这两种情况都给出了如下结论:

第二种解决方案不需要通过反射找到函数。必须在运行时之前绑定函数.第一种是使用反射。

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

票数 13
EN

Stack Overflow用户

发布于 2016-12-07 21:34:15

也许我没有理解您的问题,但是Button脚本公开了onClick事件,您可以在代码中使用添加侦听器到

下面是我使用的代码:

代码语言:javascript
运行
复制
// 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的代码:

代码语言:javascript
运行
复制
public void TestMethod ()
{
    Debug.Log ("TestMethod");   
}

有几件事要注意:

  1. 手动创建一个GameObject并向其添加一个Button组件。UI元素有点不同,因为它们有一个RectTransform,并且必须存在于要呈现的画布对象下面。
  2. 在我的示例中,我创建按钮的方式类似于如何从UI菜单项本身创建按钮(参见参考这里)。这将成功地创建它,但不会将其添加到画布下面。
  3. 最后一件事--在我的例子中,我定义的TestMethod只是打印一个日志。单击按钮时,它会记录消息,但在button的检查器中,我无法看到列出的任何onClick事件。这可能只是意味着在运行时将侦听器添加到检查器时不会刷新检查器。
票数 -1
EN

Stack Overflow用户

发布于 2020-10-16 21:21:44

因为我还不能评论,谢谢你这么多@程序员的回答!我从第二个示例中编辑了您的代码,以便在编辑器中填充UnityEvents。在两个独立的脚本中复制和粘贴代码,一个是命名菜单,另一个是MyScript。确保菜单脚本位于一个名为Editor的文件夹中。

代码语言:javascript
运行
复制
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.UI;
using UnityEditor.Events;
using UnityEngine.Events;

public class Menu : Editor
{
    [MenuItem("Test/CreateButton")]
    public static void CreateButton()
    {
        GameObject temp = new GameObject();
        temp.AddComponent<MyScript>();
        MyScript myScriptInstance = temp.GetComponent<MyScript>();
        var btn = temp.AddComponent<Button>();

        UnityAction<GameObject> action = new UnityAction<GameObject>(myScriptInstance.OnButtonClick);
        UnityEventTools.AddObjectPersistentListener<GameObject>(btn.onClick, action, temp);

        UnityAction<GameObject> action1 = new UnityAction<GameObject>(myScriptInstance.TestClicker);
        UnityEventTools.AddObjectPersistentListener<GameObject>(btn.onClick, action1, temp);

        UnityAction<GameObject> action2 = new UnityAction<GameObject>(myScriptInstance.TestClicker);
        UnityEventTools.AddObjectPersistentListener<GameObject>(myScriptInstance.test_Event, action2, temp);


    }
}

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

public class MyScript : MonoBehaviour
{

    public UnityEvent test_Event = new UnityEvent();

    public void OnButtonClick(GameObject sender)
    {
        Debug.Log("Button Clicked");
    }

    public void TestClicker(GameObject sender)
    {
        Debug.Log("Event is working");
    }

   
}
票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40655089

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档