Skip to content
This repository has been archived by the owner on Aug 7, 2021. It is now read-only.

GlobalEvents

Porrith Suong edited this page Apr 28, 2018 · 3 revisions

4. Global Events

What are Global Events?

Global Events are functionalities which affect many objects and occur throughout the entirity of the game.

For example, take an alarm system. An alarm can be considered a global event - it can affect enemy AI, doors, a time constraint, etc. Instead of introducing the alarm system as a dependency for each object, we can decouple the alarm system and subscribe when an alarm activates to other components. This introduces a relationship between the alarm and the AI, doors, and a timer system without having a hard dependency.

Each system can define how they're affected in a generic manner and can be subscribed.

How do they work?

The Global Event System uses Delegates for method subscription, unsubscription, and invocations. Delegates in C# work like function pointers found commonly in C/C++. You can read more about Delegates on the MSDN page.

The GlobalEventHandler contains a global event table which allows any void method with 0 to 4 arguments to be subscribed.

Once subscribed, another instance can invoke the subscribed method. Take the alarm system as an example.

Note: All instances which subscribed to the GlobalEventHandler will get invoked. So, if you have a duplicated alarm system then every alarm system will be activated with no guarenteed order. This is a limitation of a global event system.

using GlobalEvents; // Use the GlobalEvents namespace
using UnityEngine;
using UnityEngine.AI;

public class EnemyAI : MonoBehaviour {

    private NavMeshAgent agent;

    private void OnEnable() {
        // Subscribe the event
        GlobalEventHandler.SubscribeEvent("MoveToAlarm", MoveTo);
    }

    private void OnDisable() {
        // Unsubscribe the event
        GlobalEventHandler.UnsubscribeEvent("MoveToAlarm", MoveTo);
    }

    private void Start() {
        agent = GetComponent<NavMeshAgent>();
    }
    
    // Move the agent to a position and invoke this method.
    private void MoveTo(Vector3 position) {
        agent.SetDestination(position);
    }
}

public class AlarmSystem: MonoBehaviour {

    public Transform playerTransform;

    private bool isActive;

    private void Start() {
        isActive = false;
        playerTransform = GameObject.FindGameObjectWithTag("Player");
    }

    private void Update() {
        // If the player is within 5 meters of the alarm
        if (Vector3.Distance(playerTransform.position, transform.position) < 5f) {
            if (!isActive) {
                // Invoke the GlobalEventHandler and pass the position of the alarm as an argument
                GlobalEventHandler.InvokeEvent("MoveToAlarm", transform.position);
            }
        }
    }
}