原文地址:http://bbs.9ria.com/thread-153258-1-1.html
原工程地址:https://github.com/djandrew/UnityEventManager
多年的Flash开发,我非常欣赏Flash的事件系统。Uinty对象通信所使用的方法SendMessage在多数情况下是工作正常,但如果在一个具有无数引用其他对象的GameObject的大型项目进行反射,那问题就来了。
我用C#在Uinty中所写的第一个东西,就是管理抽象类的事件管理系统。究其核心,EventManager使用也是SendMessage,并对游戏对象[gameObject]有直接引用,但若有事件发生,其便会对需求进行分解,不同的类间会有信息共享,这样事件对象就知道如何互相通信。
若有任何建议或修正,欢迎留言。
EventManager.cs (十按,本链接为注释译版,若觉得某译不妥请对照英文版自行勘误)
- /*
- Event Manager
- Static manager for handling an event driven communication model in Unity.
- This is similar to Adobe Flash's event listener model used in ActionScript.
-
- Copyright © 2012 Dustin Andrew
- dustin.andrew@gmail.com
- http://www.dustinandrew.me/
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- http://www.gnu.org/licenses/
- */
-
- /*
- * Setup:
- * Create an empty GameObject and add the EventManager script to it.
- * Create custom event classes that extend the CustomEvent.
- *
- * Restrictions & Tips:
- * DO NOT add event listeners in the Awake() method!
- * This is used by the EventManager to initialize.
- * Change this class' Execution Order to before default time if you need to work around this.
- * Use the Start() method to setup your events.
- * Make event listener callback functions public.
- * Extend the CustomEvent class when creating your events.
- * Use custom variables in your custom events over the arguments hashtable to maintain class abstraction
- * Clean up and remove event listeners when objects are destroyed.
- * Events are not received if the listener gameObject.active is false.
- *
- * Examples:
- *
- * // setup event listeners
- * void Start() {
- * EventManager.instance.addEventListener(CustomEventObj.EVENT_TO_LISTEN_TO, gameObject, "OnSomethingHappened");
- * }
- *
- * // remove event listeners
- * void OnDestroy() {
- * if (gameObject) {
- * // remove a single event
- * EventManager.instance.removeEventListener(CustomEventObj.EVENT_TO_LISTEN_TO, gameObject);
- * // remove all events
- * EventManager.instance.removeAllEventListeners(gameObject);
- * }
- * }
- *
- * // get values passed by events
- * public void OnSomethingHappened(CustomEventObj evt) {
- * Debug.Log((datatype)evt.arguments["value"]);
- * // or if using custom vars instead of arguments hashtable
- * Debug.Log(evt.rockOn);
- * }
- *
- * // dispatch events
- * void TriggerEvent() {
- * CustomEventObj evt = new CustomEventObj(CustomEventObj.EVENT_TO_TRIGGER);
- * evt.arguments.Add("value", 3);
- * EventManager.instance.dispatchEvent(evt);
- * }
- *
- * // create custom events
- * using UnityEngine;
- * using System.Collections;
- *
- * public class CustomEventObj : CustomEvent {
- *
- * // event types
- * public static string MY_EVENT_1 = "my_event_1";
- * public static string MY_EVENT_2 = "my_event_2";
- *
- * // optionally add custom variables instead of using the arguments hashtable
- * public int myCustomEventVar1 = 0;
- * public bool rockOn = true;
- *
- * public CustomEventObj(string eventType = "") {
- * type = eventType;
- * }
- * }
- *
- */
-
- using UnityEngine;
- using System.Collections;
-
- // internal event listener model
- internal class EventListener {
- public string name;
- public GameObject listener;
- public string function;
- }
-
- // Custom event class, extend when creating custom events
- public class CustomEvent {
-
- private string _type;
- private Hashtable _arguments = new Hashtable();
-
- // constructor
- public CustomEvent(string eventType = "") {
- _type = eventType;
- }
-
- // the type of event
- public string type {
- get { return _type; }
- set { _type = value; }
- }
-
- // the arguments to pass with the event
- public Hashtable arguments {
- get { return _arguments; }
- set { _arguments = value; }
- }
- }
-
- public class EventManager : MonoBehaviour {
-
- // singleton instance
- public static EventManager instance;
-
- // settings
- public bool allowSingleton = true; // EventManager class will transfer between scene changes.
- public bool allowWarningOutputs = true;
- public bool allowDebugOutputs = true;
-
- private static bool _created = false;
- private Hashtable _listeners = new Hashtable();
-
- // setup singleton if allowed
- public void Awake() {
- if (!_created && allowSingleton) {
- DontDestroyOnLoad(this);
- instance = this;
- _created = true;
- Setup();
- } else {
- if (allowSingleton) {
- if (EventManager.instance.allowWarningOutputs) {
- Debug.LogWarning("Only a single instance of " + this.name + " should exists!");
- }
- Destroy(gameObject);
- } else {
- instance = this;
- Setup();
- }
- }
- }
-
- // clear events on quit
- public void OnApplicationQuit() {
- _listeners.Clear();
- }
-
- // PUBLIC *******************************
-
- // Add event listener
- public bool addEventListener(string eventType, GameObject listener, string function) {
- if (listener == null || eventType == null) {
- if (allowWarningOutputs) {
- Debug.LogWarning("Event Manager: AddListener failed due to no listener or event name specified.");
- }
- return false;
- }
- recordEvent(eventType);
- return recordListener(eventType, listener, function);
- }
-
- // Remove event listener
- public bool removeEventListener(string eventType, GameObject listener) {
- if (!checkForEvent(eventType)) return false;
-
- ArrayList listenerList = _listeners[eventType] as ArrayList;
- foreach (EventListener callback in listenerList) {
- if (callback.name == listener.GetInstanceID().ToString()) {
- listenerList.Remove(callback);
- return true;
- }
- }
- return false;
- }
-
- // Remove all event listeners
- public void removeAllEventListeners(GameObject listener) {
- foreach (EventListener callback in _listeners) {
- if (callback.listener.GetInstanceID().ToString() == listener.GetInstanceID().ToString()) {
- _listeners.Remove(callback);
- }
- }
- }
-
- // Dispatch an event
- public bool dispatchEvent(CustomEvent evt) {
- string eventType = evt.type;
- if (!checkForEvent(eventType)) {
- if (allowWarningOutputs) {
- Debug.LogWarning("Event Manager: Event \"" + eventType + "\" triggered has no listeners!");
- }
- return false;
- }
-
- ArrayList listenerList = _listeners[eventType] as ArrayList;
- if (allowDebugOutputs) {
- Debug.Log("Event Manager: Event " + eventType + " dispatched to " + listenerList.Count + ((listenerList.Count == 1) ? " listener." : " listeners."));
- }
- foreach (EventListener callback in listenerList) {
- if (callback.listener && callback.listener.active) {
- callback.listener.SendMessage(callback.function, evt, SendMessageOptions.DontRequireReceiver);
- }
- }
- return false;
- }
-
- // PRIVATE *******************************
-
- private void Setup() {
- // TO DO: Self create GameObject if not already created
- }
-
- // see if event already exists
- private bool checkForEvent(string eventType) {
- if (_listeners.ContainsKey(eventType)) return true;
- return false;
- }
-
- // record event, if it doesn't already exists
- private bool recordEvent(string eventType) {
- if (!checkForEvent(eventType)) {
- _listeners.Add(eventType, new ArrayList());
- }
- return true;
- }
-
- // delete event, if not already removed
- private bool deleteEvent(string eventType) {
- if (!checkForEvent(eventType)) return false;
- _listeners.Remove(eventType);
- return true;
- }
-
- // check if listener exists
- private bool checkForListener(string eventType, GameObject listener) {
- if (!checkForEvent(eventType)) {
- recordEvent(eventType);
- }
-
- ArrayList listenerList = _listeners[eventType] as ArrayList;
- foreach (EventListener callback in listenerList) {
- if (callback.name == listener.GetInstanceID().ToString()) return true;
- }
- return false;
- }
-
- // record listener, if not already recorded
- private bool recordListener(string eventType, GameObject listener, string function) {
- if (!checkForListener(eventType, listener)) {
- ArrayList listenerList = _listeners[eventType] as ArrayList;
- EventListener callback = new EventListener();
- callback.name = listener.GetInstanceID().ToString();
- callback.listener = listener;
- callback.function = function;
- listenerList.Add(callback);
- return true;
- } else {
- if (allowWarningOutputs) {
- Debug.LogWarning("Event Manager: Listener: " + listener.name + " is already in list for event: " + eventType);
- }
- return false;
- }
- }
- }
原文链接:http://www.dustinandrew.me/blog/2012/10/9/unity3d-c-event-manager.html
翻译词数:225