Creating Global “Broadcast” Events with UnityEvents

I want to use the new UnityEvents to broadcast global game events, but examples of how to do this and my knowledge of the new system are very limited at the moment. I think the best way to do this is by re-creating the “Event Trigger” script, but with my own custom events. After looking at the UI source code I now know how to create my own version with custom events like so:

Custom Interface and Event:

using UnityEngine;
using UnityEngine.EventSystems;

// interface you implement in your MB to receive events
public interface IGameStartHandler : IEventSystemHandler
{
    void OnGameStart (GameStartData eventData);
}

// Custom data we will send via the event system
public class GameStartData : BaseEventData
{
    public string m_GameStartData;
 
    public GameStartData(EventSystem eventSystem, string data)
        : base(eventSystem)
    {
        m_GameStartData = data;
    }
}

// container class that holds the execution logic
// called by the event system to delecate the call to
// the intercea
public static class GameStartEvents
{
    // call that does the mapping
    private static void Execute(IGameStartHandler handler, BaseEventData eventData)
    {
        // The ValidateEventData makes sure the passed event data is of the correct type
        handler.OnGameStart (ExecuteEvents.ValidateEventData<GameStartData> (eventData));
    }
 
    // helper to return the functor that should be invoked
    public static ExecuteEvents.EventFunction<IGameStartHandler> GameStartEventHandler
    {
        get { return Execute; }
    }
}

Custom “Trigger Event” like script to setup listener object events

using System;
using System.Collections.Generic;
using UnityEngine.Events;

namespace UnityEngine.EventSystems
{
    public class CustomTrigger :
        MonoBehaviour,
        IGameStartHandler
    {
        public enum EventType
        {
            GameStart = 0,
            GameEnd = 1
        }

        [Serializable]
        public class TriggerEvent : UnityEvent<BaseEventData>
        { }
     
        [Serializable]
        public class Entry
        {
            public EventType eventID = EventType.GameStart;
            public TriggerEvent callback = new TriggerEvent();
        }
     
        public List<Entry> delegates;
     
        protected CustomTrigger()
        { }
     
        private void Execute(EventType id, BaseEventData eventData)
        {
            if (delegates != null)
            {
                for (int i = 0, imax = delegates.Count; i < imax; ++i)
                {
                    var ent = delegates[i];
                    if (ent.eventID == id && ent.callback != null)
                        ent.callback.Invoke(eventData);
                }
            }
        }

        public virtual void OnGameStart(GameStartData eventData)
        {
            Execute(EventType.GameStart, eventData);
        }
    }
}

However, I’m stuck on how exactly I’m supposed to go about sending the event to each listener automatically through a method. The only example I’ve found is for a custom input module that sends the events to a list of objects:

//Custom input module that can send the events
public class MyInputModule : BaseInputModule
{
    // list of objects to invoke on
    public GameObject[] m_TargetObjects;
 
    // called each tick on active input module
    public override void Process()
    {
        // if we don't have targets return
        if (m_TargetObjects == null || m_TargetObjects.Length == 0)
            return;
     
        // for each target invoke our custom event
        foreach (var target in m_TargetObjects)
            ExecuteEvents.Execute (target, new GameStartData (eventSystem, "Game Start Data"), GameStartEvents.GameStartEventHandler);
    }
}

But I just want to call the event on all listeners form a method, like with a C# event:

            if(OnGameStart != null)
                OnGameStart();

I have to admit I’m in over my head here and having a hard time wrapping my brain around all this code. :face_with_spiral_eyes: Am I going about this completely wrong? Any suggestions or advice would be greatly appreciated.

1 Like

Is there like an upvote option for this? Because I’m trying to figure out how to extend the BaseInputModules and frankly the documentation on it is pretty bad.

** @CDMcGwire ** Sounds like your looking for the Feedback section. Once there you can submit ideas for things you think Unity should improve and others can up-vote them.

1 Like

I have actually done that now. :smile:

@CDMcGwire FYI: The best source of information I’ve found so far for learning how to extend/modify the input module system is the UI source code itself on Bitbucket.