Unity3D C#事件管理:EventManager
2014-06-10 16:11
399 查看
原文地址: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
原工程地址: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
相关文章推荐
- Unity3D C#事件管理:EventManager
- Unity3D C#事件管理
- Unity3D教程:Unity3D中的C#事件
- C# 事件和Unity3D
- C#事件和Unity3d
- 【转】【UNITY3D 游戏开发之七】C# 中的委托、事件、匿名函数、Lambda 表达式
- 【转】【UNITY3D 游戏开发之七】C# 中的委托、事件、匿名函数、Lambda 表达式
- C# 事件和Unity3D
- Unity3D C# 委托和事件(之二)
- C# 事件和Unity3D
- C# 事件和Unity3D
- Unity3D 中使用C# 委托和事件(之二)
- C# 事件和Unity3D
- C# 事件和Unity3D
- C# 事件和Unity3D
- C# 事件和Unity3D
- C# 事件和Unity3D
- C# 事件和Unity3D
- Unity3D学习之C#的代理和事件
- Unity3D中的C#事件