我正在寻找此Manager using UnityEvent的c#委托版。我不想使用它,因为UnityEvent在大多数时候比C#事件慢。
有关如何实现这一点的任何线索?
答案 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
这是@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);