Unity 按钮单击"未触发"事件



我查看了此处处理相同问题的帖子,但它既没有说明问题所在,也没有解决我的问题。

我创建了一个在面板中带有许多按钮的 Canvas 预制件。我在运行时实例化预制件并抓取面板中的所有Button对象。然后,我将一个侦听器添加到调用相同clicked()方法的所有按钮的onClick()事件中

public class GameOptions
{
private GameObject canvas;
public GameOptions(GameObject canvas)
{
this.canvas = canvas;
GameObject.Instantiate(canvas);        
Text[] textObjects = canvas.GetComponentsInChildren<Text>();
Button[] buttonObjects = canvas.GetComponentsInChildren<Button>();
for (int i = 0; i < buttonObjects.Length; i++)
{
Debug.Log(buttonObjects[i].name);
buttonObjects[i].onClick.AddListener(() => clicked());
buttonObjects[i].onClick.Invoke();
}
}
public void clicked()
{
Debug.Log("Clicked!");
}
}

请注意,当我通过代码调用事件时,将调用clicked()并将"Clicked!"正确输出到控制台。

但是,单击时,没有任何按钮触发事件。我还注意到,检查器中 OnClick 中的 PersistentCalls.Calls 数组在运行时的所有按钮都有 0 个元素。

我在Windows 2017.4.3f1中使用Unity 10 64。

您没有抛出任何异常,并且onClick.Invoke()正在触发这一事实表明问题在于其他元素正在消耗点击次数。没有你的项目在我面前,我只能提出一些建议。

  • 确保相机和按钮之间没有 UI 元素(如透明面板或图像(;您可以在运行时在对象周围移动,以查看它们是否太近并消耗单击。
  • 确保父画布没有Interactable设置为 false 的CanvasGroup
  • 查找任何可能阻挡光线投射的空对象/碰撞体/侦听器。

祝你好运!


编辑

在重新阅读您的代码并再次给链接的帖子一次之后,我意识到您的代码中的一个错误。

GameOptions类构造函数中,在收集对象时实际上并没有引用实例化的对象。你写了这个:

this.canvas = canvas;
GameObject.Instantiate(canvas);
Text[] textObjects = canvas.GetComponentsInChildren<Text>();

如果您查看到底发生了什么,则将字段canvas分配给传递到构造函数参数中的预制件。进行赋值后,使用参数实例化预制件,而不引用实例化的对象。

之后,您将在预制件上调用GetComponentsInChildren,而不是实例化的对象本身。这就是触发onClick.Invoke()的原因,因为对象存在于预制件上;它们只是不是您要查找的对象。

我已经重构了您的构造函数,这应该可以解决您的问题。

public GameOptions(GameObject canvas)
{
//here we instantiate the canvas item, assigning it to the field
this.canvas = GameObject.Instantiate(canvas);  
//then we reference the field item, instead of the parameter item
Text[] textObjects = this.canvas.GetComponentsInChildren<Text>();
Button[] buttonObjects = this.canvas.GetComponentsInChildren<Button>();
for(int i = 0; i < buttonObjects.Length; i++)
{
Debug.Log(buttonObjects[i].name);
buttonObjects[i].onClick.AddListener(() => clicked());
buttonObjects[i].onClick.Invoke();
}
}

一些注意事项

  • 你应该使用Canvas项而不是GameObject,即使你从不使用Canvas类的任何成员;它使以后更容易阅读,并防止你意外构造new GameOptions(someRandomButton)当你试图访问子类时,它不会做任何事情。Canvas对象继承自GameObject,因此您将拥有所需的一切。
  • 您应该考虑使用不同的命名方案;这是高度主观的意见,如果您搜索SO,则对该主题存在很多争论。就个人而言,我在私有字段(例如private GameObject _canvas;(上选择了下划线前缀,这使我毫不怀疑我没有忘记this,因为参数和字段本质上具有独特而独特的命名方案。

对我的建议持保留态度!有很多方法可以解决问题,所以最终选择最适合您的方法。

只是为了帮助更多遇到这个烦人问题的人。

除了EventSystemCanvas的一般配置之外,还有另一个原因导致我在自己的程序中发现的 UI 按钮无响应,我认为这可能是大多数人的原因。

当您自己添加camera(很常见(而不对其进行标记时,会出现此问题。如果您不知道标记它,那么它很可能是您的原因。

关键点:与standalone input module一起使用的camera必须标记为MainCamera。否则,它将无法识别没有碰撞体的物体。

相关内容

  • 没有找到相关文章

最新更新