如何统一实现事件发送器-事件接收器游戏对象?

时间:2019-05-27 10:25:56

标签: c# unity3d

我有“ A”类,它将发送事件“ a”。预订事件“ a”的类将对此事件做出反应。其他类可以订阅事件“ a”,而无需更改类“ A”中的任何内容;

现在,统一执行此操作的最合理方法是什么?是否已经有一些消息传递系统可以做到这一点?

如果没有,我是否应该像EventManager类那样将订户类存储在数组中并调用其方法?

1 个答案:

答案 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();
        }
    }
}

全局EventHandler

或者,如果您想进行封装,则可以像前面提到的那样为所有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()
    {
        //
    }
}

注意:请在智能手机上输入内容,因此没有保修,但我希望这个想法会清楚。