Unity3D C#事件管理:EventManager

原文地址:http://bbs.9ria.com/thread-153258-1-1.html

原project地址:https://github.com/djandrew/UnityEventManager

多年的Flash开发。我很赞赏Flash的事件系统。

Uinty对象通信所使用的方法SendMessage在多数情况下是工作正常,但假设在一个具有无数引用其它对象的GameObject的大型项目进行反射,那问题就来了。


我用C#在Uinty中所写的第一个东西,就是管理抽象类的事件管理系统。

究其核心。EventManager使用也是SendMessage。并对游戏对象[gameObject]有直接引用,但若有事件发生。其便会对需求进行分解,不同的类间会有信息共享,这样事件对象就知道怎样互相通信。



若有不论什么建议或修正。欢迎留言。



EventManager.cs(十按。本链接为凝视译版,若认为某译不妥请对比英文版自行勘误)

  1. /*
  2.     Event Manager
  3.     Static manager for handling an event driven communication model in Unity.
  4.     This is similar to Adobe Flash's event listener model used in ActionScript.
  5.      
  6.     Copyright © 2012 Dustin Andrew
  7.     dustin.andrew@gmail.com
  8.     http://www.dustinandrew.me/
  9.      
  10.     This program is free software: you can redistribute it and/or modify
  11.     it under the terms of the GNU General Public License as published by
  12.     the Free Software Foundation, either version 3 of the License, or 
  13.     any later version.

  14.     This program is distributed in the hope that it will be useful,
  15.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.     GNU General Public License for more details.

  18.     http://www.gnu.org/licenses/
  19. */

  20. /* 
  21. *  Setup:
  22. *  Create an empty GameObject and add the EventManager script to it.
  23. *  Create custom event classes that extend the CustomEvent.

  24. *  Restrictions & Tips:
  25. *  DO NOT add event listeners in the Awake() method! 
  26. *  This is used by the EventManager to initialize.
  27. *  Change this class' Execution Order to before default time if you need to work around this.
  28. *  Use the Start() method to setup your events.
  29. *  Make event listener callback functions public.
  30. *  Extend the CustomEvent class when creating your events.
  31. *  Use custom variables in your custom events over the arguments hashtable to maintain class abstraction
  32. *  Clean up and remove event listeners when objects are destroyed.
  33. *  Events are not received if the listener gameObject.active is false.

  34. *  Examples:

  35. *  // setup event listeners
  36. *  void Start() {
  37. *      EventManager.instance.addEventListener(CustomEventObj.EVENT_TO_LISTEN_TO, gameObject, "OnSomethingHappened");
  38. *  }
  39. *  
  40. *  // remove event listeners
  41. *  void OnDestroy() {
  42. *      if (gameObject) {
  43. *          // remove a single event
  44. *          EventManager.instance.removeEventListener(CustomEventObj.EVENT_TO_LISTEN_TO, gameObject);
  45. *          // remove all events
  46. *          EventManager.instance.removeAllEventListeners(gameObject);
  47. *      }
  48. *  }

  49. *  // get values passed by events
  50. *  public void OnSomethingHappened(CustomEventObj evt) {
  51. *      Debug.Log((datatype)evt.arguments["value"]);
  52. *      // or if using custom vars instead of arguments hashtable
  53. *      Debug.Log(evt.rockOn);      
  54. *  }

  55. *  // dispatch events
  56. *  void TriggerEvent() {
  57. *      CustomEventObj evt = new CustomEventObj(CustomEventObj.EVENT_TO_TRIGGER);
  58. *      evt.arguments.Add("value", 3);
  59. *      EventManager.instance.dispatchEvent(evt);
  60. *  }

  61. *  // create custom events
  62. *  using UnityEngine;
  63. *  using System.Collections;

  64. *  public class CustomEventObj : CustomEvent {

  65. *      // event types
  66. *      public static string MY_EVENT_1 = "my_event_1";
  67. *      public static string MY_EVENT_2 = "my_event_2";

  68. *      // optionally add custom variables instead of using the arguments hashtable
  69. *      public int myCustomEventVar1 = 0;
  70. *      public bool rockOn = true;

  71. *      public CustomEventObj(string eventType = "") {
  72. *         type = eventType;
  73. *      }
  74. *  }

  75. */

  76. using UnityEngine;
  77. using System.Collections;

  78. // internal event listener model
  79. internal class EventListener {
  80.     public string name;
  81.     public GameObject listener;
  82.     public string function; 
  83. }

  84. // Custom event class, extend when creating custom events
  85. public class CustomEvent {
  86.      
  87.     private string _type;
  88.     private Hashtable _arguments = new Hashtable();
  89.      
  90.     // constructor
  91.     public CustomEvent(string eventType = "") {
  92.         _type = eventType;
  93.     }
  94.      
  95.     // the type of event
  96.     public string type {
  97.         get { return _type; }
  98.         set { _type = value; }
  99.     }
  100.      
  101.     // the arguments to pass with the event
  102.     public Hashtable arguments {
  103.         get { return _arguments; }
  104.         set { _arguments = value; }
  105.     }
  106. }

  107. public class EventManager : MonoBehaviour {
  108.      
  109.     // singleton instance
  110.     public static EventManager instance;
  111.      
  112.     // settings
  113.     public bool allowSingleton = true; // EventManager class will transfer between scene changes.
  114.     public bool allowWarningOutputs = true;
  115.     public bool allowDebugOutputs = true;
  116.      
  117.     private static bool _created = false;   
  118.     private Hashtable _listeners = new Hashtable(); 
  119.      
  120.     // setup singleton if allowed
  121.     public void Awake() {
  122.         if (!_created && allowSingleton) {
  123.             DontDestroyOnLoad(this);
  124.             instance = this;
  125.             _created = true;
  126.             Setup();
  127.         } else {
  128.             if (allowSingleton) {
  129.                 if (EventManager.instance.allowWarningOutputs) {
  130.                     Debug.LogWarning("Only a single instance of " + this.name + " should exists!");
  131.                 }
  132.                 Destroy(gameObject);
  133.             } else {
  134.                 instance = this;
  135.                 Setup();
  136.             }
  137.         }
  138.     }
  139.      
  140.     // clear events on quit
  141.     public void OnApplicationQuit() {
  142.         _listeners.Clear();
  143.     }
  144.      
  145.     // PUBLIC *******************************
  146.      
  147.     // Add event listener
  148.     public bool addEventListener(string eventType, GameObject listener, string function) {
  149.         if (listener == null || eventType == null) {
  150.             if (allowWarningOutputs) {
  151.                 Debug.LogWarning("Event Manager: AddListener failed due to no listener or event name specified.");
  152.             }
  153.             return false;
  154.         }
  155.         recordEvent(eventType);
  156.         return recordListener(eventType, listener, function);
  157.     }
  158.      
  159.     // Remove event listener
  160.     public bool removeEventListener(string eventType, GameObject listener) {
  161.         if (!checkForEvent(eventType)) return false;
  162.          
  163.         ArrayList listenerList = _listeners[eventType] as ArrayList;
  164.         foreach (EventListener callback in listenerList) {
  165.             if (callback.name == listener.GetInstanceID().ToString()) {
  166.                 listenerList.Remove(callback);
  167.                 return true;
  168.             }
  169.         }
  170.         return false;
  171.     }
  172.      
  173.     // Remove all event listeners
  174.     public void removeAllEventListeners(GameObject listener) {
  175.         foreach (EventListener callback in _listeners) {
  176.             if (callback.listener.GetInstanceID().ToString() == listener.GetInstanceID().ToString()) {
  177.                 _listeners.Remove(callback);
  178.             }
  179.         }
  180.     }
  181.      
  182.     // Dispatch an event
  183.     public bool dispatchEvent(CustomEvent evt) {
  184.         string eventType = evt.type;
  185.         if (!checkForEvent(eventType)) {
  186.             if (allowWarningOutputs) {
  187.                 Debug.LogWarning("Event Manager: Event "" + eventType + "" triggered has no listeners!");
  188.             }
  189.             return false;
  190.         }
  191.          
  192.         ArrayList listenerList = _listeners[eventType] as ArrayList;
  193.         if (allowDebugOutputs) {
  194.             Debug.Log("Event Manager: Event " + eventType + " dispatched to " + listenerList.Count + ((listenerList.Count == 1) ? " listener." : " listeners."));
  195.         }
  196.         foreach (EventListener callback in listenerList) {
  197.             if (callback.listener && callback.listener.active) {
  198.                 callback.listener.SendMessage(callback.function, evt, SendMessageOptions.DontRequireReceiver);
  199.             }
  200.         }
  201.         return false;
  202.     }
  203.      
  204.     // PRIVATE *******************************
  205.      
  206.     private void Setup() {
  207.         // TO DO: Self create GameObject if not already created
  208.     }
  209.      
  210.     // see if event already exists
  211.     private bool checkForEvent(string eventType) {
  212.         if (_listeners.ContainsKey(eventType)) return true;
  213.         return false;
  214.     }
  215.      
  216.     // record event, if it doesn't already exists
  217.     private bool recordEvent(string eventType) {
  218.         if (!checkForEvent(eventType)) {
  219.             _listeners.Add(eventType, new ArrayList());
  220.         }
  221.         return true;
  222.     }
  223.      
  224.     // delete event, if not already removed
  225.     private bool deleteEvent(string eventType) {
  226.         if (!checkForEvent(eventType)) return false;
  227.         _listeners.Remove(eventType);
  228.         return true;
  229.     }
  230.      
  231.     // check if listener exists
  232.     private bool checkForListener(string eventType, GameObject listener) {
  233.         if (!checkForEvent(eventType)) {
  234.             recordEvent(eventType);
  235.         }
  236.          
  237.         ArrayList listenerList = _listeners[eventType] as ArrayList;
  238.         foreach (EventListener callback in listenerList) {
  239.             if (callback.name == listener.GetInstanceID().ToString()) return true;
  240.         }
  241.         return false;
  242.     }
  243.      
  244.     // record listener, if not already recorded
  245.     private bool recordListener(string eventType, GameObject listener, string function) {
  246.         if (!checkForListener(eventType, listener)) {
  247.             ArrayList listenerList = _listeners[eventType] as ArrayList;
  248.             EventListener callback = new EventListener();
  249.             callback.name = listener.GetInstanceID().ToString();
  250.             callback.listener = listener;
  251.             callback.function = function;
  252.             listenerList.Add(callback);
  253.             return true;
  254.         } else {
  255.             if (allowWarningOutputs) {
  256.                 Debug.LogWarning("Event Manager: Listener: " + listener.name + " is already in list for event: " + eventType);
  257.             }
  258.             return false;
  259.         }
  260.     }
  261. }
复制代码



原文链接:http://www.dustinandrew.me/blog/2012/10/9/unity3d-c-event-manager.html

翻译词数:225

原文地址:https://www.cnblogs.com/jzssuanfa/p/7287220.html