我正在使用UnityEvent寻找此Manager的 c#委托版本。我不想使用它,因为UnityEvent在大多数时候都比C#事件慢。
关于如何实现这一点的任何线索?
您可以使用Action实际上是这样声明的委托:
Action
namespace System { public delegate void Action(); }
1。 从使用委托的名称空间UnityAction替换所有with 。Action``System
UnityAction
Action``System
2。 全部thisEvent.AddListener(listener);替换为thisEvent += listener;
thisEvent.AddListener(listener);
thisEvent += listener;
3。 全部thisEvent.RemoveListener(listener);替换为 thisEvent -= listener;
thisEvent.RemoveListener(listener);
thisEvent -= listener;
这是Unity 原始 版本的修改版本,可EventManager移植为使用委托/动作。
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](); } } }
测试脚本:
下面的测试脚本通过每2秒触发一次事件来测试事件。
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!"); } }
带参数:
从其他问题来看,大多数人都在问如何支持参数。这里是。您可以使用class/ struct作为参数,然后将要传递的所有变量添加到此类/结构中的函数中。我将EventParam举一个例子。随意EventParam在代码末尾添加/删除要在事件结构中传递的变量。
class
struct
EventParam
using System; using System.Collections; using System.Collections.Generic; using UnityEngine; public class EventManager : MonoBehaviour { private Dictionary<string, Action<EventParam>> 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<EventParam>>(); } } public static void StartListening(string eventName, Action<EventParam> listener) { Action<EventParam> 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<EventParam> listener) { if (eventManager == null) return; Action<EventParam> 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, EventParam eventParam) { Action<EventParam> thisEvent = null; if (instance.eventDictionary.TryGetValue(eventName, out thisEvent)) { thisEvent.Invoke(eventParam); // OR USE instance.eventDictionary[eventName](eventParam); } } } //Re-usable structure/ Can be a class to. Add all parameters you need inside it public struct EventParam { public string param1; public int param2; public float param3; public bool param4; }
public class Test : MonoBehaviour { private Action<EventParam> someListener1; private Action<EventParam> someListener2; private Action<EventParam> someListener3; void Awake() { someListener1 = new Action<EventParam>(SomeFunction); someListener2 = new Action<EventParam>(SomeOtherFunction); someListener3 = new Action<EventParam>(SomeThirdFunction); StartCoroutine(invokeTest()); } IEnumerator invokeTest() { WaitForSeconds waitTime = new WaitForSeconds(0.5f); //Create parameter to pass to the event EventParam eventParam = new EventParam(); eventParam.param1 = "Hello"; eventParam.param2 = 99; eventParam.param3 = 43.4f; eventParam.param4 = true; while (true) { yield return waitTime; EventManager.TriggerEvent("test", eventParam); yield return waitTime; EventManager.TriggerEvent("Spawn", eventParam); yield return waitTime; EventManager.TriggerEvent("Destroy", eventParam); } } void OnEnable() { //Register With Action variable EventManager.StartListening("test", someListener1); EventManager.StartListening("Spawn", someListener2); EventManager.StartListening("Destroy", someListener3); //OR Register Directly to function EventManager.StartListening("test", SomeFunction); EventManager.StartListening("Spawn", SomeOtherFunction); EventManager.StartListening("Destroy", SomeThirdFunction); } void OnDisable() { //Un-Register With Action variable EventManager.StopListening("test", someListener1); EventManager.StopListening("Spawn", someListener2); EventManager.StopListening("Destroy", someListener3); //OR Un-Register Directly to function EventManager.StopListening("test", SomeFunction); EventManager.StopListening("Spawn", SomeOtherFunction); EventManager.StopListening("Destroy", SomeThirdFunction); } void SomeFunction(EventParam eventParam) { Debug.Log("Some Function was called!"); } void SomeOtherFunction(EventParam eventParam) { Debug.Log("Some Other Function was called!"); } void SomeThirdFunction(EventParam eventParam) { Debug.Log("Some Third Function was called!"); } }