So I’m taking a step here from my normal iOS/Android style simple(r) games, and attempting to create a more complex game. I’ve wanted to implement events/delegates for awhile, but I feel like I don’t have the conceptual scheme down in my head. I was hoping someone could just walk me through where events are commonly employed?
For instance, I understand that there is some Event Manager, which, when some condition is met, will send out an event. Event Listeners are subscribed to a particular event, and when that event occurs, executes a particular function. But is it general practice to have a single Event Manager in your game that controls and oversees all events? If that’s the case, how would you handle things like, for example, combat? Wouldn’t each Unit have to have an Event Manager and an Event Listener, and I’m not sure how to even set up subscriptions for that.
Anyway, I really just wanted to know when it’s practical to use events?
thats the “problem”. if you have 50 units each one have to be registered with all necessary events (dying, beeing damaged, attacking etc). therefore its usually better to have one global event messenger like this one. then each unit calls the particular event on this manager and it executes the delegate. this way the listeners can register at a single global place. and the unit can give required information to the messenger fe to calculate score etc.
hint: often the events are strings which are stored in a dictionary. i use enums instead as it have some advantages:
no typos, compiler ensures that you only use existing events (“Event” + “event” are different).
enums can be switched/foreached.
possibly faster as the hashcode of an int (enum) is the int itself.
easier to rename/refactor/obfuscate with proper tools.
most importantly enums utilize intellisense and thus allow faster coding.
I would also like some conceptual advice regarding events. The video quoted above is very good and demonstrates a simple situation where an EventManager class sets up the delegate and the event and triggers the event which any other class can subscribe to. That’s fine, but I find myself wanting to trigger events from elsewhere. For example lets say I want certain player input to trigger an event, so I don’t want to move some or all player input handling into EventManager but I do want to trigger an event. C# does not allow an event to be triggered from outside the class it belongs to so I find myself creating a public method to do the task, e.g. inside EventManager will be a method that can be called by anyone and will then trigger the event.
I’ve taken the example code from the video and split it into three to demonstrate my approach. I’ve moved the GUI buttons that trigger the event into the EventTrigger class. I would really like to know if I have missed the point of events here, or whether this is a perfectly acceptable approach?
using UnityEngine;
using System.Collections;
public class EventManager : MonoBehaviour {
public delegate void PowerUpHandler (bool isPoweredUp);
public static event PowerUpHandler onPoweredUp;
public static void triggerOnPoweredUp(bool isPoweredUp) {
if (onPoweredUp != null)
onPoweredUp(isPoweredUp);
}
}
using UnityEngine;
using System.Collections;
public class EventListener : MonoBehaviour {
void OnEnable() {
EventManager.onPoweredUp += onPoweredUp;
}
void OnDisable() {
EventManager.onPoweredUp -= onPoweredUp;
}
void onPoweredUp (bool isPoweredUp) {
if (isPoweredUp) {
renderer.material.color = Color.red;
StartCoroutine(bounce());
} else {
renderer.material.color = new Color(1.0f, 1.0f, 1.0f, 1.0f);
StopAllCoroutines();
}
}
public IEnumerator bounce() {
while (true) {
Vector3 pos = transform.position;
pos.y = Mathf.PingPong(Time.time * 10.0f, 2.0f);
transform.position = pos;
yield return null;
}
}
}
using UnityEngine;
using System.Collections;
public class EventTrigger : MonoBehaviour {
void OnGUI() {
if (GUI.Button(new Rect(5,5,150,40), "Power Up"))
EventManager.triggerOnPoweredUp(true);
if (GUI.Button(new Rect(5,50,150,40), "Power Up Over"))
EventManager.triggerOnPoweredUp(false);
}
}