Dar*_*ook 5 c# unity-game-engine unity-ui
我查看了此处处理相同问题的帖子,但它既没有说明问题所在,也没有解决我的问题。
我创建了一个 Canvas 预制件,面板内有许多按钮。我在运行时实例化预制件并抓取Button面板内的所有对象。onClick()然后,我为调用相同clicked()方法的所有按钮添加一个事件侦听器
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!");
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,当我通过代码调用该事件时,clicked()将被调用并“单击!” 正确输出到控制台。
但是,单击时没有任何按钮触发事件。我还注意到,检查器中 OnClick 中的 PersistentCalls.Calls 数组在运行时为所有按钮都有 0 个元素。
我在 Windows 10 64 中使用 Unity 2017.4.3f1。
事实上,您没有抛出任何异常,并且正在onClick.Invoke()触发,这表明问题是其他一些元素正在消耗点击。由于没有你的项目在我面前,我只能提出一些建议。
CanvasGroupwith没有Interactable设置为 false。祝你好运!
重新阅读您的代码并再次查看链接的帖子后,我意识到您的代码中存在错误。
在GameOptions类构造函数中,收集对象时实际上并未引用实例化的对象。你写了这个:
this.canvas = canvas;
GameObject.Instantiate(canvas);
Text[] textObjects = canvas.GetComponentsInChildren<Text>();
Run Code Online (Sandbox Code Playgroud)
如果您查看到底发生了什么,就会将该字段分配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();
}
}
Run Code Online (Sandbox Code Playgroud)
Canvasitem 而不是;它使以后的阅读变得更容易,并防止您意外构建当您尝试访问子级时不会执行任何操作的情况。该对象继承自,因此您将拥有所需的一切。GameObjectCanvasnew GameOptions(someRandomButton)CanvasGameObjectprivate GameObject _canvas;,这让我零怀疑我没有忘记 a this,因为本质上参数和字段将具有不同且唯一的命名方案。请对我的建议持保留态度!解决问题的方法有很多种,因此最终选择最适合您的方法。