2017-02-03 10 views

답변

9

당신은 실제로 어떤 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!"); 
    } 
} 
+2

당신이 최고입니다! – ywj7931

+0

더 느리게되는 UnityEvent는 어떤 추가 작업을합니까? 기본적으로, 우리는'Action'과 커스텀 이벤트 매니저를 사용하여 더 빠른 속도로 거래하고 있습니까? –

+0

@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