我有自己的自定义UnityEvent,正在尝试添加侦听器。
我在许多其他UI对象(例如按钮,下拉菜单,切换按钮等)上使用了AddListener
,因此我理解了这一过程。但是,当我Invoke
我的UnityEvent时,它根本不会触发。
我没有收到任何错误消息,并且在阅读和研究之后,一切看起来都正确。因此,不确定下一步该怎么做。
这是一个旋转时发出的对象。
这是我代码的基础:
using UnityEngine.Events;
public class Rotator: MonoBehaviour
{
public UnityEvent OnRotate;
int angle = 0;
int newAngle = 0;
void Start()
{
OnRotate = new UnityEvent();
}
void Update()
{
newAngle = (int)transform.rotation.eulersAngles.z;
if (newAngle != angle)
{
print ("Actual Instance ID: " + GetInstanceID());
print ("Invoking!");
OnRotate.Invoke();
angle = newAngle;
}
}
}
和
public class Owner: MonoBehaviour
{
public Rotator rotator;
void Start()
{
print ("Rotator Instance ID: " + rotator.GetInstanceID());
rotator.OnRotate.AddListener(
() => UpdateRotation()
);
}
void UpdateRotation()
{
print ("Invoked!");
}
}
当Rotator
的角度改变时,我在控制台中得到了它:
Actual Instance ID: 11234
Rotator Instance ID: 11234
Invoking!
实例ID是为了确保我正在使用相同的对象并且不会无所事事。它们匹配,所以我在听正在发射的物体。 但是,听众不会开火。我已经尝试了与委托等的不同组合,但是都是一样的。没有错误。它只是不调用。
很明显,我做错了什么,但这是什么?
感谢您的帮助。
答案 0 :(得分:1)
您可以使用之前在First Version of your Question中提供的代码来完全回答问题的新编辑版本!
正如我试图告诉您的那样……如果您在代码中的任何位置都进行OnRotate = new UnityEvent()
,那么您当然会擦除此刻之前的所有持久性回调和所有运行时回调!
简而言之
只需将其保留为
public UnityEvent OnRotate;
,您甚至不必再考虑它。
要了解为什么将其放在Awake
中也能起作用,请简单查看Order of Execution for Event Functions
→每个游戏对象/组件首先调用Awake
和OnEnabled
。然后,一旦GameObject / Component处于活动状态,就会调用所有Start
方法。
在每个块(Awake
和OnEnable
和(Start
中,除非您通过{{3 }},您可以定义Owner
只是在Rotator
之前运行。然后将两者都包含在Start
中也将再次起作用。
如果您在public
字段上执行此操作,为什么它也起作用?
→因为此字段是序列化的。这意味着它会在Inspector中自动初始化,然后与Scene或预制资产(包括任何持久回调)一起存储。
然后,后来Unity重新使用字段的序列化版本,因此实际上您可以完全删除new UnityEvent();
,因为它对序列化字段没有任何影响!无论如何,它总是会自动初始化!
答案 1 :(得分:0)
好的,我发现了问题所在。 我的问题现在是“为什么?”。
我更改了以下代码:
public UnityEvent OnRotate;
void Start() {
OnRotate = new UnityEvent();
}
到
public UnityEvent OnRotate = new UnityEvent();
void Start() {
}
现在可以使用了。
尽管,现在我考虑了一下,Awake()
是它们都在初始化之前启动的方法,而Start()
是创建对象时的方法。因此,Start()
中的Rotator
可能在<{>}添加Owner
之后被称为。