【问题标题】:Unity onClick.addlistener not workingUnity onClick.addlistener 不工作
【发布时间】:2016-10-14 07:17:50
【问题描述】:

当事件发生时,我会在运行时加载 Canvas 预制件。画布内部只有一个面板,而面板又具有 2 个按钮。我正在尝试将 OnClick 事件添加到脚本中的这两个按钮,但它只适用于第一个按钮! 我有以下两行代码一个接一个:

GameObject.Find("RestartButton").GetComponent<Button>().onClick.AddListener(() => RestartClicked());
GameObject.Find("ViewButton").GetComponent<Button>().onClick.AddListener(() => ViewClicked());

回调仅适用于 RestartButton,不适用于 ViewButton。 这可能是一件非常小的事情,但我广泛搜索了 Google 和 Bing,但仍然一无所知,因此我们将不胜感激。

谢谢!

编辑:

脚本实例化预制件并尝试通过 GameObject.Find() 引用预制件中的两个按钮,因为一旦调用了 Instantiate,Canvas 就应该在层次结构中处于活动状态。 我还打开了将按钮附加到侦听器以进行调试的代码部分。我认为它根本不附加听众。

void Start () {

    SetupScene();

    var prefab = Resources.Load("RestartOrViewPrefab");
    if (prefab == null)
    {
        Debug.LogAssertion("Prefab missing!");
        return;
    }
    restartCanvas = (GameObject)Instantiate(prefab);
    Button btn = GameObject.Find("ViewButton").GetComponent<Button>();
    btn.onClick.RemoveAllListeners();
    btn.onClick.AddListener(() => ViewToggle());
    Button btn2 = GameObject.Find("RestartButton").GetComponent<Button>();
    btn2.onClick.AddListener(() => RestartClicked());
}

private void RestartClicked()
{
    Debug.Log("RESTARTING");
    SetupScene();
}

private void ViewToggle()
{
    Debug.Log("TOGGLE");
    if (freshStart)
    {
        //Something here
        freshStart = false;
    }
    else
    {
        //Something else here
        freshStart = true;
    }
}

【问题讨论】:

  • 我看不出你的代码有什么问题。您可以发布其余的代码吗?也许还有其他我们不知道的事情正在发生
  • 可以贴出ViewClicked()的代码吗?如何判断回调是否无效?
  • 当然。很抱歉只发布了两行代码。我认为解释会公正。我正在更新我的帖子。

标签: user-interface button unity3d onclick


【解决方案1】:

确定您没有收到任何空引用错误,并检查按钮的拼写,在您的第二个函数中输出一些调试日志,看看它是否到达那里

【讨论】:

  • 我放了调试日志,但它没有到达那里。奇怪的是,如果我将回调替换为 Reset 和 View 按钮,ViewClicked 确实会被 ResetButton 调用。此外,ViewButton 很少开始工作并随机停止工作。我认为问题出在 Canvas 中的 EventHandler 上。有什么建议?我将发布更全面的代码视图,以便您理解。再次感谢先生。
【解决方案2】:

所以我花了两天时间来解决我的问题。显然,为您刚刚实例化的预制件中的游戏对象执行GameObject.Find() 是行不通的。我们总是需要使用 Instantiate() 方法返回的 GameObject 来查找预制件中的任何组件。 如果您的预制件非常大/复杂(假设您有 15 个按钮并且需要用一个做某事),我用来使场景工作的代码可能不是最佳解决方案,但它确实有效。 :) 我替换了以下代码行:

Button btn = GameObject.Find("ViewButton").GetComponent<Button>();
btn.onClick.RemoveAllListeners();
btn.onClick.AddListener(() => ViewToggle());
Button btn2 = GameObject.Find("RestartButton").GetComponent<Button>();
btn2.onClick.AddListener(() => RestartClicked());

使用以下代码行:

Button[] buttons = restartCanvas.GetComponentsInChildren<Button>();

    foreach(Button but in buttons)
    {
        if(but.gameObject.name == "RestartButton")
            but.onClick.AddListener(() => RestartClicked());
        else if(but.gameObject.name == "ViewButton")
            but.onClick.AddListener(() => ViewToggle());
    }

所以我只是重用了我得到参考的restartCanvas

restartCanvas = (GameObject)Instantiate(prefab);

希望这对某人有所帮助。 :)

【讨论】:

  • 在你实例化预制件后只是改变它的名字,我问你是否得到任何空引用但你没有回复
  • 我确实回复了您的评论(见下文)。我没有得到任何空引用。更改预制件的名称有什么帮助呢?在不更改名称的情况下,Unity 可以找到我正在寻找的游戏对象,但不会设置或更改它们的任何属性。
  • 只需使用这个按钮 mybutton = instantiate() ,这样你就不需要查找功能,可以使用同一个按钮添加 onlick 监听器
【解决方案3】:

我在另一个帖子中回答了这个问题,但我会在这里为仍然需要此信息的人回答这个问题。 您实例化的按钮是其子级的 GameObject 必须有一个 CanvasRenderer 组件。 我不确定为什么会这样,但确实如此。 一旦按钮 GameObject 的父级拥有 CanvasRenderer,您就可以像往常一样调用myButton.onClick.AddListener(() =&gt; MyMethod(MyArgs));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-11
    • 2015-06-14
    • 2018-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多