带有委托而不是UnityEvent的Unity EventManager
我正在使用UnityEvent寻找此Manager的
c#委托版本。我不想使用它,因为UnityEvent在大多数时候都比C#事件慢。
关于如何实现这一点的任何线索?
回答:
您可以使用Action
实际上是这样声明的委托:
namespace System{
public delegate void Action();
}
从使用委托的名称空间UnityAction
替换所有with 。Action``System
全部thisEvent.AddListener(listener);
替换为thisEvent += listener;
全部thisEvent.RemoveListener(listener);
替换为 thisEvent -= listener;
这是Unity 原始 版本的修改版本,可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
在代码末尾添加/删除要在事件结构中传递的变量。
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!");
}
}
以上是 带有委托而不是UnityEvent的Unity EventManager 的全部内容, 来源链接: utcz.com/qa/427443.html