A lightweight generic event bus system for Unity, allowing decoupled communication between components using strongly-typed events.
This system supports:
- Registering listeners for events
- Raising events with or without arguments
- Automatic type safety using generics
You can add DumbInjector to your Unity project in two ways:
git submodule add https://github.com/oultrox/SimpleBus.git Assets/SimpleBus- Open Window > Package Manager
- Click the + button and choose Add package from git URL
- Enter:
https://github.com/oultrox/SimpleBus.gitAll events should implement the IEvent interface.
public interface IEvent { }The generic static event bus class.
Tmust implementIEvent.- Supports
Register,Deregister, andRaisemethods.
EventBus<MapGeneratedEvent>.Raise(new MapGeneratedEvent());IEventListener<T>defines event callbacks.EventListener<T>is a concrete class you can instantiate with actions.
public class EventListener<T> : IEventListener<T> where T : IEvent
{
public Action<T> OnEvent { get; set; }
public Action OnEventNoArgs { get; set; }
// Constructors and add/remove helpers included
}Events must implement the IEvent interface.
It’s usually preferred to define them as structs since they are lightweight and reduce allocations:
// Events can be empty
public struct MapGeneratedEvent : IEvent{}
// Or have parameters
public struct ShowMazePathEvent : IEvent
{
public string mazePathName;
}Create a listener and register it with the EventBus:
private EventListener<MapGeneratedEvent> _mapGeneratedListener;
public MazeGenerator(IPathFinder pathFinder, IEntitySpawner spawner)
{
_mapGeneratedListener = new EventListener<MapGeneratedEvent>(Generate);
EventBus<MapGeneratedEvent>.Register(_mapGeneratedListener);
}
// Event callback
void Generate(MapGeneratedEvent e)
{
Debug.Log("Map generated!");
}You can also register listeners without arguments:
new EventListener<ShowMazePathEvent>(() => ShowPath()).Add(...);Any component can raise an event, and all registered listeners will be notified:
//Example
void GenerateMap()
{
EventBus<MapGeneratedEvent>.Raise(new MapGeneratedEvent());
}
void ShowPath()
{
EventBus<ShowMazePathEvent>.Raise(new ShowMazePathEvent());
}When a listener is no longer needed (e.g., on destroy):
EventBus<MapGeneratedEvent>.Deregister(_mapGeneratedListener);public class MazeManager : MonoBehaviour
{
private readonly MapGeneratedEvent _mapGenerated = new();
private readonly ShowMazePathEvent _showMazePath = new();
void Start()
{
InjectListeners();
}
void InjectListeners()
{
generateButton.onClick.AddListener(() => EventBus<MapGeneratedEvent>.Raise(_mapGenerated));
showPathButton.onClick.AddListener(() => EventBus<ShowMazePathEvent>.Raise(_showMazePath));
}
}- Listeners can subscribe multiple actions.
- Events are type-safe, avoiding the need for string-based events.
- Supports both argument and no-argument callbacks.
EventBus<T>.Clear()can reset all listeners for a specific type (useful for editor testing).
- Decouple systems:
UIcan listen toGameLogicevents without direct references. - Avoid tight coupling: Components don’t need to know who is listening.
- Debug configurations to let the users disable the logs.