In this lesson, you will learn how to build a decoupled messaging system using ScriptableObject event channels to trigger actions across your project without requiring direct object references.
The Problem of Tight Coupling
In many projects, a Player script might need to tell the UIManager to update the health bar. If the Player holds a direct reference to the UIManager, changing one often breaks the other. This "spaghetti" code makes scaling difficult. We can solve this by using a "middleman" that exists independently of any specific scene or game object.
Designing the Event Channel
A ScriptableObject is the perfect candidate for this because it exists in your project files as an asset. You can create an EventChannel that acts as a broadcast hub. Any system can "subscribe" to this channel, and any system can "raise" an event through it, without either side knowing the other exists.
Here is a simple implementation of an Action based event channel:
using UnityEngine;
using System;
[CreateAssetMenu(menuName = "Events/Game Event")]
public class GameEventChannel : ScriptableObject
{
public event Action OnEventRaised;
public void RaiseEvent()
{
OnEventRaised?.Invoke();
}
}
How to Use It
- The Broadcaster: Any component (e.g.,
PlayerHealth) holds a reference to thisGameEventChannelasset. When the player takes damage, it callsmyEventChannel.RaiseEvent(). - The Listener: The
UIManagerholds a reference to the same asset. In itsOnEnablemethod, it subscribes:myEventChannel.OnEventRaised += UpdateUI;.
Because both components rely on the same ScriptableObject asset, they communicate perfectly without ever needing to know the other exists. If you decide to remove the UI or add a sound-effects manager that also listens to that channel, you don't have to touch a single line of code in your Player script. This modularity is a pillar of clean, professional architecture.
Key Takeaway: By using ScriptableObject Event Channels, you turn direct dependencies into indirect, event-driven relationships, allowing systems to interact seamlessly without being tightly coupled.