我有“ A”类,它将发送事件“ a”。预订事件“ a”的类将对此事件做出反应。其他类可以订阅事件“ a”,而无需更改类“ A”中的任何内容;
现在,统一执行此操作的最合理方法是什么?是否已经有一些消息传递系统可以做到这一点?
如果没有,我是否应该像EventManager类那样将订户类存储在数组中并调用其方法?
答案 0 :(得分:3)
可能有很多方法可以做到这一点。
public class A : MonoBehaviour
{
public static List<A> AvailableAs = new List<A>();
private void Awake()
{
if(!AvailableAs.Contains(this)) AvailableAs.Add(this);
}
private void OnDestroy()
{
if(AvailableAs.Contains(this)) AvailableAs.Remove(this);
}
public void SomePublicMethod()
{
// magic
}
}
并使用它,例如喜欢
public class B : MonoBehaviour
{
// run the method on all currently registered A instances
public void DoIt()
{
foreach(var a in A.AvailableAs)
{
a.SomePublicMethod();
}
}
}
或者,如果您想进行封装,则可以像前面提到的那样为所有A提供一个全局事件处理程序
namespace ANamespace
{
public static class AEventHandler
{
internal static event Action OnInvokeA;
public static void InvokeAEvent()
{
if(OnInvokeA != null) OnInvokeA.Invoke();
}
}
}
在A中有
namespace ANamespace
{
public class A : MonoBehaviour {
private void Awake()
{
// it is save to remove a callback first even
// if it was not added yet. This makes sure it is
// added only once always
AEventHandler.OnIvokeA -= SomePrivateMethod;
AEventHandler.OnIvokeA += SomePrivateMethod;
}
private void OnDestroy()
{
AEventHandler.OnIvokeA -= SomePrivateMethod;
}
private void SomePrivateMethod()
{
// magic
}
}
}
现在在B
中,您宁愿做
// invoke the event and whoever is added as listener will do
// whatever he registered
// in this case all A instances execute their method
AEventHandler.InvokeAEvent();
但是,如果您只有一个类A
引发事件,并且您希望其他人对此事件做出反应,则只需使用UnityEvent
之类的
public class A : MonoBehaviour
{
public UnityEvent OnSomethingHappened = new UnityEvent();
private void SomeMethodIWillRun()
{
//...
OnSomethingHappened.Invoke();
}
}
现在,您可以通过拖动GameObjects / Components并选择要调用的方法,轻松地在Unity Inspector中向该事件添加回调。 (实际上,onClick
组件的Button
事件使用的是同一件事;))
您仍然可以在运行时通过脚本添加回调,例如
public class B : MonoBehaviour
{
public A referenceToA;
private void Start()
{
referenceToA.OnSomethingHappened.AddCallback(OnASomethingHappened);
}
private void OnDestroy()
{
referenceToA.OnSomethingHappened.RemoveCallback(OnASomethingHappened)
}
private void OnASomethingHappened()
{
//
}
}
注意:请在智能手机上输入内容,因此没有保修,但我希望这个想法会清楚。