带有委托而不是UnityEvent的Unity EventManager

时间:2017-02-03 22:48:43

标签: c# unity3d

我正在寻找此Manager using UnityEvent的c#委托版。我不想使用它,因为UnityEvent在大多数时候比C#事件慢。

有关如何实现这一点的任何线索?

3 个答案:

答案 0 :(得分:17)

您可以使用cannot get Cannot GET /users/dashboard 实际上是这样声明的委托:

/dashboard/dashboard

1 。使用Action命名空间中的namespace System { public delegate void Action(); } 替换所有UnityAction。{/ p>

2 。将所有Action替换为System

3 。将所有thisEvent.AddListener(listener);替换为thisEvent += listener;

这是Unity的original thisEvent.RemoveListener(listener);的修改版本移植到使用委托/操作。

没有参数:

thisEvent -= listener;

测试脚本:

下面的测试脚本通过每2秒触发一次事件来测试事件。

EventManager

使用参数:

从其他问题来看,大多数人都在问如何支持参数。这里是。您可以使用using System; using System.Collections; using System.Collections.Generic; using UnityEngine; public class EventManager : MonoBehaviour { private Dictionary<string, Action> eventDictionary; private static EventManager eventManager; public static EventManager instance { get { if (!eventManager) { eventManager = FindObjectOfType(typeof(EventManager)) as EventManager; if (!eventManager) { Debug.LogError("There needs to be one active EventManger script on a GameObject in your scene."); } else { eventManager.Init(); } } return eventManager; } } void Init() { if (eventDictionary == null) { eventDictionary = new Dictionary<string, Action>(); } } public static void StartListening(string eventName, Action listener) { Action thisEvent; if (instance.eventDictionary.TryGetValue(eventName, out thisEvent)) { //Add more event to the existing one thisEvent += listener; //Update the Dictionary instance.eventDictionary[eventName] = thisEvent; } else { //Add event to the Dictionary for the first time thisEvent += listener; instance.eventDictionary.Add(eventName, thisEvent); } } public static void StopListening(string eventName, Action listener) { if (eventManager == null) return; Action thisEvent; if (instance.eventDictionary.TryGetValue(eventName, out thisEvent)) { //Remove event from the existing one thisEvent -= listener; //Update the Dictionary instance.eventDictionary[eventName] = thisEvent; } } public static void TriggerEvent(string eventName) { Action thisEvent = null; if (instance.eventDictionary.TryGetValue(eventName, out thisEvent)) { thisEvent.Invoke(); // OR USE instance.eventDictionary[eventName](); } } } / public class TestScript: MonoBehaviour { private Action someListener; void Awake() { someListener = new Action(SomeFunction); StartCoroutine(invokeTest()); } IEnumerator invokeTest() { WaitForSeconds waitTime = new WaitForSeconds(2); while (true) { yield return waitTime; EventManager.TriggerEvent("test"); yield return waitTime; EventManager.TriggerEvent("Spawn"); yield return waitTime; EventManager.TriggerEvent("Destroy"); } } void OnEnable() { EventManager.StartListening("test", someListener); EventManager.StartListening("Spawn", SomeOtherFunction); EventManager.StartListening("Destroy", SomeThirdFunction); } void OnDisable() { EventManager.StopListening("test", someListener); EventManager.StopListening("Spawn", SomeOtherFunction); EventManager.StopListening("Destroy", SomeThirdFunction); } void SomeFunction() { Debug.Log("Some Function was called!"); } void SomeOtherFunction() { Debug.Log("Some Other Function was called!"); } void SomeThirdFunction() { Debug.Log("Some Third Function was called!"); } } 作为参数,然后将要传递的所有变量添加到此类/ struct中的函数中。我将以class为例。您可以在此代码末尾的事件struct结构中添加/删除要传递的变量。

EventParam

测试脚本:

EventParam

答案 1 :(得分:0)

!接受的答案不完整!

作为一个懒惰的程序员,我只是复制了Programmer编写的内容,但是在注释部分遇到了同样的问题。

程序员的解决方案不适用于同一事件的多个订阅者。

这是修复程序(对参数版本进行了相同的更改):

Delegate/datasource

这是我在此发布的StackOverflow问题的链接

Why do I get a clone of Action<> when getting from dictionary?

  

当您调用TryGetValue(eventName,输出thisEvent)时,您将提供字典将值写入到的引用。您没有获得对Dictionary内部内容的引用(我的意思是,您没有得到对Dictionary结构的深入了解,这意味着分配给它不会修改Dictionary)。

答案 2 :(得分:0)

聚会晚了一点,@programmer的答案确实有很大帮助,但是如果有人想用返回值触发事件,仍然想分享答案,当然主持人会知道如何处理这个答案。 / p>

.net提供func和action,func 或func

这是@programmers代码,具有返回值:

 private Dictionary<string, Func<EventParam,bool>> eventDictionary;

private static EventManager eventManager;

public static EventManager instance
{
    get
    {
        if (!eventManager)
        {
            eventManager = FindObjectOfType(typeof(EventManager)) as EventManager;

            if (!eventManager)
            {
                Debug.LogError("There needs to be one active EventManger script on a GameObject in your scene.");
            }
            else
            {
                eventManager.Init();
            }
        }
        return eventManager;
    }
}

void Init()
{
    if (eventDictionary == null)
    {
        eventDictionary = new Dictionary<string, Func<EventParam, bool>>();
    }
}

public static void StartListening(string eventName,Func<EventParam, bool> listener)
{
    Func<EventParam, bool> thisEvent;
    if (instance.eventDictionary.TryGetValue(eventName, out thisEvent))
    {

        thisEvent += listener;


        instance.eventDictionary[eventName] = thisEvent;
    }
    else
    {

        thisEvent += listener;
        instance.eventDictionary.Add(eventName, thisEvent);
    }
}

public static void StopListening(string eventName, Func<EventParam, bool> listener)
{
    if (eventManager == null) return;
    Func<EventParam, bool> thisEvent;
    if (instance.eventDictionary.TryGetValue(eventName, out thisEvent))
    {

        thisEvent -= listener;


        instance.eventDictionary[eventName] = thisEvent;
    }
}

public static bool TriggerEvent(string eventName, EventParam eventParam)
{
    Func<EventParam, bool> thisEvent = null;
    if (instance.eventDictionary.TryGetValue(eventName, out thisEvent))
    {
        bool value;
        value = thisEvent.Invoke(eventParam);
        return value;
    }
    return false;
}

}

公共结构EventParam { 公共字符串param1;

}

所以现在可以这样调用Trigger了

EventParam newparam = new EventParam();
    newparam.param1 = "Ty Mr Programmer this custom eventmanager";
    bool checkme;
    checkme =  EventManager.TriggerEvent("API", newparam);