By Published On: October 7th, 2022Categories: General1 CommentTags: , , ,

There’s loads of sources on this topic, even on Unity’s own Learn page! My goal with this code was to create a lightweight version that I can drop into any project if I need a quick event system.  Most of the code examples I’ve found online have been based around wiring up events using the Inspector, or having a one-to-one relationship between each Event and its Listener(s).  The system below replaces the GameListenerEvent middleman class from the Unity Learn example with the standard Action type, letting you assign your delegate for each Event Listener in your code. 

The code below creates base classes for Action, Action<T1>, and Action<T1,T2> delegates, similar to the UnityAction versions (which you could probably replace Action with, if you want to remove your dependence on the System library).  You can go ahead and add T3 and beyond if you find the need for them.

Use the standard OnEnable() => eventObject.RegisterListener(delegate); and OnDisable() => eventObject.UnregisterListener(delegate); syntax to register your Listeners.

This code was adapted from the code in the discussion located here.

using System;
using System.Collections.Generic;
using UnityEngine;
public abstract class BaseGameEvent : ScriptableObject
{
#if UNITY_EDITOR
[TextArea] public string developerDescription = "";
#endif
private readonly List<Action> listeners = new ();
public void Raise()
{
for (var i = listeners.Count – 1; i >= 0; i–)
{
listeners[i].Invoke();
}
}
public void RegisterListener(Action listener)
{
if (!listeners.Contains(listener)) { listeners.Add(listener); }
}
public void UnregisterListener(Action listener)
{
if (listeners.Contains(listener)) { listeners.Remove(listener); }
}
}
public abstract class BaseGameEvent<T1> : BaseGameEvent
{
private readonly List<Action<T1>> listeners = new ();
public void Raise(T1 t1)
{
for (var i = listeners.Count – 1; i >= 0; i–)
{
listeners[i].Invoke(t1);
}
}
public void RegisterListener(Action<T1> listener)
{
if (!listeners.Contains(listener)) { listeners.Add(listener); }
}
public void UnregisterListener(Action<T1> listener)
{
if (listeners.Contains(listener)) { listeners.Remove(listener); }
}
}
public abstract class BaseGameEvent<T1,T2> : BaseGameEvent
{
private readonly List<Action<T1,T2>> listeners = new ();
public void Raise(T1 t1, T2 t2)
{
for (var i = listeners.Count – 1; i >= 0; i–)
{
listeners[i].Invoke(t1, t2);
}
}
public void RegisterListener(Action<T1,T2> listener)
{
if (!listeners.Contains(listener)) { listeners.Add(listener); }
}
public void UnregisterListener(Action<T1,T2> listener)
{
if (listeners.Contains(listener)) { listeners.Remove(listener); }
}
}
/* USE:
*************
[CreateAssetMenu()]
public class GameEvent : BaseGameEvent {}
public class IntGameEvent : BaseGameEvent<int> {}
public class IntStringGameEvent : BaseGameEvent<int,string> {}
**************
*/
///
/// examples of the three components required to utilize the system:
///
// the Scriptable Object Event definition
[CreateAssetMenu]
public class CoinGameEvent : BaseGameEvent<int>
{}
// the MonoBehaviour on each Coin to collect
public class Coin : MonoBehaviour
{
// the Scriptable Object Event we created via the Create Asset menu
[SerializeField] private CoinGameEvent coinEvent;
// raise our coin event whenever the user picks up a coin
void OnTriggerEnter2D(Collider2D other)
{
coinEvent.Raise(1);
Destroy(gameobject);
}
}
// this can also be a ScriptableObject since they still have OnEnable() and OnDisable() methods
public class CoinManager : MonoBehaviour
{
int coins;
// register to Listen for the Coin Event
void OnEnable() => coinEvent.RegisterListener(AddCoins);
void OnDisable() => coinEvent.UnregisterListener(AddCoins);
// add the number of coins in the Event to our total
void AddCoins(int value) => coins += value;
}
Projectile Arcing in Unity with Animation Curves
Simple Unity Hex Grid Framework

One Comment

  1. […] my original post on Lightweight ScriptableObject Events, I’ve made some minor variations to the version of code I’ve been using in production. […]

Leave a Reply