您的位置:首页 > 移动开发 > Unity3D

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: