이 Manager using UnityEvent의 C# 델리게이트 버전을 찾고 있습니다. 나는 UnityEvent이 C# 이벤트보다 더 느리기 때문에 이것을 사용하고 싶지 않습니다.유니티 이벤트 대신 델리게이트가있는 유니티 이벤트 매니저
이것을 구현하는 방법에 대한 단서가 있습니까?
이 Manager using UnityEvent의 C# 델리게이트 버전을 찾고 있습니다. 나는 UnityEvent이 C# 이벤트보다 더 느리기 때문에 이것을 사용하고 싶지 않습니다.유니티 이벤트 대신 델리게이트가있는 유니티 이벤트 매니저
이것을 구현하는 방법에 대한 단서가 있습니까?
당신은 실제로 어떤 Action
를 사용할 수있는 대리자는 다음과 같이 선언 :
namespace System
{
public delegate void Action();
}
1 .Replace에게 Action
와 모든 UnityAction
을 위임을 사용하는 System
네임 스페이스에서.
2 .Replace 모든 thisEvent.AddListener(listener);
thisEvent -= listener;
와 thisEvent.RemoveListener(listener);
모든 thisEvent += listener;
3 .Replace와 여기 유니티의 사용 originalEventManager
이식 대리인/동작의 수정 된 버전이다. 매개 변수없이
:
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!");
}
}
당신이 최고입니다! – ywj7931
더 느리게되는 UnityEvent는 어떤 추가 작업을합니까? 기본적으로, 우리는'Action'과 커스텀 이벤트 매니저를 사용하여 더 빠른 속도로 거래하고 있습니까? –
@ScottChamberlain 메모리 할당 + 리플렉션을 너무 많이 사용합니다. 그것의 유일한 이점은 Editor에서 public으로 만들 수 있고 Editor에서 serialize 된 이후에 이벤트를 할당 할 수 있다는 것입니다. 그것은 다른 모든 것들에서 실패하고 실제 게임에 사용되어서는 안됩니다. 직접 테스트하거나 [this] (https://www.reddit.com/r/Unity3D/comments/35sa5h/unityevent_vs_delegate_event_benchmark_for_those/#bottom-comments) 및 [this] (http://jacksondunstan.com)을 확인할 수 있습니다./articles/3335). – Programmer