1 using UnityEngine; 2 using System.Collections; 3 using System.Collections.Generic; 4 //----------------------------------------------------------- 5 //Enum defining all possible game events 6 //More events should be added to the list 7 public enum EVENT_TYPE {GAME_INIT, 8 GAME_END, 9 AMMO_CHANGE, 10 HEALTH_CHANGE, 11 DEAD}; 12 //----------------------------------------------------------- 13 //Singleton EventManager to send events to listeners 14 //Works with IListener implementations 15 public class EventManager : MonoBehaviour 16 { 17 #region C# properties 18 //----------------------------------------------------------- 19 //Public access to instance 20 public static EventManager Instance 21 { 22 get{return instance;} 23 set{} 24 } 25 #endregion 26 27 #region variables 28 //Internal reference to Notifications Manager instance (singleton design pattern) 29 private static EventManager instance = null; 30 31 // Declare a delegate type for events 32 public delegate void OnEvent(EVENT_TYPE Event_Type, Component Sender, object Param = null); 33 34 //Array of listener objects (all objects registered to listen for events) 35 private Dictionary<EVENT_TYPE, List<OnEvent>> Listeners = new Dictionary<EVENT_TYPE, List<OnEvent>>(); 36 #endregion 37 //----------------------------------------------------------- 38 #region methods 39 //Called at start-up to initialize 40 void Awake() 41 { 42 //If no instance exists, then assign this instance 43 if(instance == null) 44 { 45 instance = this; 46 DontDestroyOnLoad(gameObject); //Prevent object from being destroyed on scene exit 47 } 48 else //Instance already exists, so destroy this one. This should be a singleton object 49 DestroyImmediate(this); 50 } 51 //----------------------------------------------------------- 52 /// <summary> 53 /// Function to add specified listener-object to array of listeners 54 /// </summary> 55 /// <param name="Event_Type">Event to Listen for</param> 56 /// <param name="Listener">Object to listen for event</param> 57 public void AddListener(EVENT_TYPE Event_Type, OnEvent Listener) 58 { 59 //List of listeners for this event 60 List<OnEvent> ListenList = null; 61 62 //New item to be added. Check for existing event type key. If one exists, add to list 63 if(Listeners.TryGetValue(Event_Type, out ListenList)) 64 { 65 //List exists, so add new item 66 ListenList.Add(Listener); 67 return; 68 } 69 70 //Otherwise create new list as dictionary key 71 ListenList = new List<OnEvent>(); 72 ListenList.Add(Listener); 73 Listeners.Add(Event_Type, ListenList); //Add to internal listeners list 74 } 75 //----------------------------------------------------------- 76 /// <summary> 77 /// Function to post event to listeners 78 /// </summary> 79 /// <param name="Event_Type">Event to invoke</param> 80 /// <param name="Sender">Object invoking event</param> 81 /// <param name="Param">Optional argument</param> 82 public void PostNotification(EVENT_TYPE Event_Type, Component Sender, object Param = null) 83 { 84 //Notify all listeners of an event 85 86 //List of listeners for this event only 87 List<OnEvent> ListenList = null; 88 89 //If no event entry exists, then exit because there are no listeners to notify 90 if(!Listeners.TryGetValue(Event_Type, out ListenList)) 91 return; 92 93 //Entry exists. Now notify appropriate listeners 94 for(int i=0; i<ListenList.Count; i++) 95 { 96 if(!ListenList[i].Equals(null)) //If object is not null, then send message via interfaces 97 ListenList[i](Event_Type, Sender, Param); 98 } 99 } 100 //----------------------------------------------------------- 101 //Remove event type entry from dictionary, including all listeners 102 public void RemoveEvent(EVENT_TYPE Event_Type) 103 { 104 //Remove entry from dictionary 105 Listeners.Remove(Event_Type); 106 } 107 //----------------------------------------------------------- 108 //Remove all redundant entries from the Dictionary 109 public void RemoveRedundancies() 110 { 111 //Create new dictionary 112 Dictionary<EVENT_TYPE, List<OnEvent>> TmpListeners = new Dictionary<EVENT_TYPE, List<OnEvent>>(); 113 114 //Cycle through all dictionary entries 115 foreach(KeyValuePair<EVENT_TYPE, List<OnEvent>> Item in Listeners) 116 { 117 //Cycle through all listener objects in list, remove null objects 118 for(int i = Item.Value.Count-1; i>=0; i--) 119 { 120 //If null, then remove item 121 if(Item.Value[i].Equals(null)) 122 Item.Value.RemoveAt(i); 123 } 124 125 //If items remain in list for this notification, then add this to tmp dictionary 126 if(Item.Value.Count > 0) 127 TmpListeners.Add (Item.Key, Item.Value); 128 } 129 130 //Replace listeners object with new, optimized dictionary 131 Listeners = TmpListeners; 132 } 133 //----------------------------------------------------------- 134 //Called on scene change. Clean up dictionary 135 void OnLevelWasLoaded() 136 { 137 RemoveRedundancies(); 138 } 139 //----------------------------------------------------------- 140 #endregion 141 }
1 using UnityEngine; 2 using System.Collections; 3 4 public class EnemyObject : MonoBehaviour 5 { 6 //------------------------------------------------------- 7 //C# accessors for private variables 8 public int Health 9 { 10 get{return _health;} 11 set 12 { 13 //Clamp health between 0-100 14 _health = Mathf.Clamp(value, 0, 100); 15 16 //Post notification - health has been changed 17 EventManager.Instance.PostNotification(EVENT_TYPE.HEALTH_CHANGE, this, _health); 18 } 19 } 20 //------------------------------------------------------- 21 public int Ammo 22 { 23 get{return _ammo;} 24 set 25 { 26 //Clamp ammo between 0-50 27 _ammo = Mathf.Clamp(value,0,50); 28 29 //Post notification - ammo has been changed 30 EventManager.Instance.PostNotification(EVENT_TYPE.AMMO_CHANGE, this, _health); 31 } 32 } 33 //------------------------------------------------------- 34 //Internal variables for health and ammo 35 private int _health = 100; 36 private int _ammo = 50; 37 //------------------------------------------------------- 38 //Called at start-up 39 void Start() 40 { 41 //Add myself as listener for health change events 42 EventManager.Instance.AddListener(EVENT_TYPE.HEALTH_CHANGE, OnEvent); 43 } 44 //------------------------------------------------------- 45 // Update is called once per frame 46 void Update () 47 { 48 //If you press space bar, the health is reduce 49 if(Input.GetKeyDown(KeyCode.Space)) 50 { 51 //Take some damage of space bar press 52 Health -= 5; 53 } 54 } 55 //------------------------------------------------------- 56 //Called when events happen 57 public void OnEvent(EVENT_TYPE Event_Type, Component Sender, object Param = null) 58 { 59 //Detect event type 60 switch(Event_Type) 61 { 62 case EVENT_TYPE.HEALTH_CHANGE: 63 OnHealthChange(Sender, (int)Param); 64 break; 65 } 66 } 67 //------------------------------------------------------- 68 //Function called when health changes 69 void OnHealthChange(Component Enemy, int NewHealth) 70 { 71 //If health has changed of this object 72 if(this.GetInstanceID() != Enemy.GetInstanceID()) return; 73 74 Debug.Log ("Object: " + gameObject.name + " Health is: " + NewHealth.ToString()); 75 } 76 //------------------------------------------------------- 77 }