AceLand Unity Packages
  • Home
  • Getting Started
    • Installation
    • Project Settings
    • Architecture Graph
    • Development Level
  • Tutorial
    • Create Your Package
    • Create Project Settings
  • Packages
    • Library
      • Change Log
      • Editor Tools
      • Mono
        • Follow Object
        • Singleton
      • Attributes
        • Conditional Show
        • Inspector Button
        • ReadOnly Field
      • Build Leveling
      • CVS
      • DataTools
      • Disposable Object
      • Extensions
      • Json
      • Kalman Filter
      • Optional
      • Project Setting
      • Serialization Surrogate
      • Utils
    • Event Driven
      • Change Log
      • Event Bus
      • Signal
    • Input
      • Change Log
    • Memento Service
      • Change Log
    • Node Framework
      • Change Log
      • Mono Node
    • Node For Mono (dev)
    • Player Loop Hack
      • Change Log
    • Pool
      • Change Log
    • Security (dev)
    • States
      • Change Log
    • Task Utils
      • Change Log
    • WebRequest
      • Change Log
Powered by GitBook
On this page
  • Overview
  • Key Features
  • Why Use It?
  • Quick Start
  • Event Caching
  • Advanced Usage
  • Best Practices
  1. Packages
  2. Event Driven

Event Bus

A powerful, type-safe event system for Unity with fluent interface design.

Overview

EventBus provides a robust, decoupled communication system for your Unity projects. Built with type safety and ease of use in mind, it offers a fluent interface for raising and listening to events, with or without payload data.

Key Features

  • Type-Safe Events: Uses interfaces for event definitions, ensuring compile-time type checking

  • Fluent Interface: Intuitive builder pattern for clear and concise event handling

  • Payload Support: Handle events with or without custom data payloads

  • Event Caching: Optional kick-start feature to receive the last event upon subscription

  • Zero Dependencies: Works right out of the box with no external dependencies


Why Use It?

Type-Safe Communication

No more string-based events or manual delegate management. Our EventBus ensures all event communications are type-safe and verified at compile time, eliminating runtime errors from typos or wrong event types.

Clean Architecture

  • Decoupled Systems: Services and components can communicate without direct references

  • Modular Design: Add or remove features without changing existing code

  • Easy Maintenance: Change internal logic without affecting other systems

  • Clear Dependencies: Easily track event flows through your application

Developer Experience

  • Intuitive API: Simple, fluent interface that's easy to understand and use

  • IDE Friendly: Full auto-completion support for better productivity

  • Reduced Boilerplate: No need to write custom event systems or manager classes

  • Quick Integration: Start using in minutes with minimal setup

Powerful Features

  • Event Caching: New subscribers can automatically receive the most recent event

  • Payload Support: Send any type of data with your events

  • Sender Tracking: Always know which component triggered an event

  • Flexible Subscription: Subscribe and unsubscribe at any time

Perfect For

  • Service Architecture: Connect independent services without tight coupling

  • UI Updates: Keep UI in sync with game state changes

  • Cross-Scene Communication: Share data between different scenes

  • State Management: Handle game state changes efficiently

  • Analytics Integration: Track game events without modifying core systems

Production Ready

  • Performance Optimized: Efficient event dispatching with minimal overhead

  • Memory Conscious: Small memory footprint with proper cleanup

  • Battle Tested: Reliable in production environments

  • Unity Friendly: Designed specifically for Unity projects

This lightweight yet powerful event system will help you build more maintainable and scalable Unity applications while reducing development time and potential bugs.


Quick Start

  1. Define Your Event

    // all event must be interface
    public interface IGameStartEvent : IEvent { }
    public interface IScoreUpdateEvent : IEvent { }
  2. Listen to Events (subscribe)

    // Event listener without payload
    EventBus.Event<IGameStartEvent>()    // set Event
        .WithListener(OnGameStart)       // set Listener
        .Listen();                       // subscribe
    
    // Event listener with payload
    EventBus.Event<IScoreUpdateEvent>()    // set Event
        .WithListener<int>(OnScoreUpdate)  // set Listener with payload
        .Listen();                         // start listen
    
    // Listener Methods
    // all listener will receive sender as first parameter
    // there is no limit on type of payload
    private void OnGameStart(object sender) { }
    private void OnScoreUpdate(object sender, int data) { }
  3. Raise Events

    // Simple event
    EventBus.Event<IGameStartEvent>()
        .WithSender(this)
        .Raise();
    
    // Event with payload
    EventBus.Event<IScoreUpdateEvent>()
        .WithSender(this)
        .WithData(100)
        .Raise();
  4. Unlisten from Events (unsubscribe)

    // Event listener without payload
    EventBus.Event<IGameStartEvent>()    // set Event
        .Unlisten(OnGameStart);          // unsubscribe
    
    // Event listener with payload
    EventBus.Event<IScoreUpdateEvent>()    // set Event
        .Unlisten<int>(OnScoreUpdate);     // unsubscribe

Event Caching

Use WithKickStart() when subscribing to automatically receive the most recent event data:

EventBus.Event<IScoreUpdateEvent>()
    .WithListener<int>(OnScoreUpdate)
    .WithKickStart() // Will immediately receive last score update
    .Listen();

Advanced Usage

The following example demonstrates how EventBus can elegantly connect services and UI layers without direct references, using a weather monitoring system.

Adding listener method in Event Interface can confirm correct listener method in obsersers.

using System;

public interface IWeatherUpdateEvent : IEvent
{
    // constrait observers to create listener with data type
    OnWeatherUpdate(object sender, WeatherData data);
}

public struct WeatherData
{
    public float Temperature;
    public float Humidity;
    public DateTime Timestamp;
}
using System;
using System.Collections;
using System.Threading.Tasks;
using AceLand.EventDriven.Bus;
using AceLand.TaskUtils;
using UnityEngine;

public class WeatherService : MonoBehaviour
{
    [SerializeField] private float updateInterval = 300f; // 5 minutes

    private void Start()
    {
        StartCoroutine(WeatherUpdateRoutine());
    }

    private IEnumerator WeatherUpdateRoutine()
    {
        while (true)
        {
            yield return new WaitForSeconds(updateInterval);
            yield return FetchAndBroadcastWeather();
        }
    }

    private Task FetchAndBroadcastWeather()
    {
        return Task.Run(async () =>
            {
                // Simulate web service call
                var data = await FetchWeatherData();
                
                // Broadcast to all listeners
                // raise event in main thread
                Promise.EnqueueToDispatcher(() =>
                    EventBus.Event<IWeatherUpdateEvent>()
                        .WithSender(this)
                        .WithData(data)
                        .Raise()
                );
            },
            Promise.ApplicationAliveToken
        );


    }

    // Simulate web service call
    private Task<WeatherData> FetchWeatherData()
    {
        return Task.Run(() => new WeatherData
            {
                Temperature = 25.5f,
                Humidity = 60f,
                Timestamp = DateTime.Now
            },
            Promise.ApplicationAliveToken
        );
    }
}
using AceLand.EventDriven.Bus;
using AceLand.Test;
using TMPro;
using UnityEngine;

// add the event interface to confirm correct observer listener
public class WeatherUIController : MonoBehaviour, IWeatherUpdateEvent
{
    [SerializeField] private TextMeshProUGUI temperatureText;
    [SerializeField] private TextMeshProUGUI humidityText;
    [SerializeField] private TextMeshProUGUI timestampText;

    private void OnEnable()
    {
        // Subscribe with kick-start to get latest data immediately
        EventBus.Event<IWeatherUpdateEvent>()
            .WithListener<WeatherData>(OnWeatherUpdate)
            .WithKickStart()
            .Listen();
    }

    private void OnDisable()
    {
        EventBus.Event<IWeatherUpdateEvent>()
            .Unlisten<WeatherData>(OnWeatherUpdate);
    }

    // promised correct listener
    public void OnWeatherUpdate(object sender, WeatherData data)
    {
        // Update UI elements
        temperatureText.text = $"{data.Temperature:F1}°C";
        humidityText.text = $"{data.Humidity:F0}%";
        timestampText.text = data.Timestamp.ToString("HH:mm:ss");
    }
}
using System.Collections.Generic;
using AceLand.EventDriven.Bus;
using AceLand.Test;
using UnityEngine;

// add the event interface to confirm correct observer listener
public class WeatherAnalytics : MonoBehaviour, IWeatherUpdateEven
{
    private List<WeatherData> weatherHistory = new List<WeatherData>();

    private void OnEnable()
    {
        EventBus.Event<IWeatherUpdateEvent>()
            .WithListener<WeatherData>(OnWeatherUpdate)
            .Listen();
    }

    private void OnDisable()
    {
        EventBus.Event<IWeatherUpdateEvent>()
            .Unlisten<WeatherData>(OnWeatherUpdate);
    }

    // promised correct listener
    public void OnWeatherUpdate(object sender, WeatherData data)
    {
        // Store historical data
        weatherHistory.Add(data);
        
        // Analyze trends
        AnalyzeWeatherTrends();
        
        // Update analysis visualization
        UpdateWeatherGraph();
    }

    private void AnalyzeWeatherTrends()
    {
        // Implement weather trend analysis
    }

    private void UpdateWeatherGraph()
    {
        // Update weather history visualization
    }
}

This example demonstrates several powerful features of EventBus:

  • Service Decoupling: Services can communicate without direct references

  • Multiple Listeners: Both UI and Analytics respond to the same event

  • Automatic Updates: UI receives updates as soon as new data arrives

  • Clean Architecture: Clear separation between data providers and consumers


Best Practices

  • Define events as empty interfaces

  • Use meaningful interface names (e.g., IGameStartEvent, IPlayerDeathEvent)

  • Keep event payloads simple and serializable

  • Always unsubscribe when destroying objects to prevent memory leaks

  • Consider using WithKickStart() for state-based events

  • Comfirm correct listener method by adding method in Event interface

Last updated 1 month ago

is using in this example.

Task Utils