Skilllibrary unity-scriptableobject-events
Implements the ScriptableObject event channel architecture in Unity — GameEvent SOs with Raise/Register, GameEventListener MonoBehaviours, shared variable SOs (FloatVariable, IntVariable), RuntimeSet<T> patterns, and SO-based decoupling as an alternative to singletons. Use when designing event-driven communication between Unity systems without hard references.
install
source · Clone the upstream repo
git clone https://github.com/merceralex397-collab/skilllibrary
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/merceralex397-collab/skilllibrary "$T" && mkdir -p ~/.claude/skills && cp -r "$T/13-game-engines-and-creative-tech/unity-scriptableobject-events" ~/.claude/skills/merceralex397-collab-skilllibrary-unity-scriptableobject-events && rm -rf "$T"
manifest:
13-game-engines-and-creative-tech/unity-scriptableobject-events/SKILL.mdsource content
Purpose
Guide implementation of the ScriptableObject-based event architecture pattern in Unity — where SO assets act as event channels and data containers, enabling fully decoupled communication between systems without singletons or direct references. Based on Ryan Hipple's GDC talk "Game Architecture with ScriptableObjects."
When to use this skill
- Designing event-driven communication between systems that should not reference each other directly
- Creating
ScriptableObjects that act as mediator channels between producers and consumersGameEvent - Building
MonoBehaviours that register with a GameEvent and invoke a UnityEvent responseGameEventListener - Implementing shared variable SOs (
,FloatVariable
,IntVariable
) as observable data containersStringVariable - Creating
ScriptableObjects to track collections of active objects (e.g., all enemies, all pickups)RuntimeSet<T> - Deciding between SO events, C# events (
),System.Action
, or a message busUnityEvent
Do not use this skill when
- The task is general Unity scripting without an event architecture focus — use
unity - The task involves Unreal Engine event systems (delegates, dispatchers) — use
unreal-engine - The decoupling requirement is for network replication — use
multiplayer-netcode
Operating procedure
- Create the GameEvent SO. Define a
withScriptableObject
. Include a[CreateAssetMenu(menuName="Events/GameEvent")]
for registered listeners, aList<GameEventListener>
method that iterates listeners and callsRaise()
, andOnEventRaised()
/RegisterListener
methods.UnregisterListener - Create the GameEventListener MB. A MonoBehaviour with a
field and aGameEvent
response. InUnityEvent
, callOnEnable
. IngameEvent.RegisterListener(this)
, callOnDisable
. ExposegameEvent.UnregisterListener(this)
which invokes the UnityEvent.OnEventRaised() - Wire in the inspector. Create a GameEvent asset (right-click → Events → GameEvent). On the producer, reference the GameEvent and call
. On the consumer, add a GameEventListener, assign the same GameEvent asset, and configure the UnityEvent response.Raise() - Shared variable pattern. Create
withFloatVariable : ScriptableObject
, a[CreateAssetMenu]
field, and optionally anValue
event. Consumers read from the SO directly or listen for changes. Useful for HP bars, score displays, and settings.OnValueChanged - RuntimeSet pattern. Create
with aRuntimeSet<T> : ScriptableObject
,List<T> Items
, andAdd(T)
. Objects callRemove(T)
inAdd
andOnEnable
inRemove
. Systems iterate the set withoutOnDisable
.FindObjectsOfType - Typed event variants. For events with data, create
generics:GameEvent<T>
,IntGameEvent
,FloatGameEvent
,StringGameEvent
. Each has a corresponding typed listener withVector3GameEvent
.UnityEvent<T> - Debug and validate. Add a
to every SO event for documentation. Add editor buttons to Raise events from the inspector during play mode. Log event raises with listener counts.[TextArea] string developerDescription - Choose the right event type. SO events for designer-configurable, inspector-wired, cross-scene communication. C#
/Action
for code-only, high-frequency, same-assembly events.event
for inspector-wired single-object callbacks. Enum-based event bus for rapid prototyping only.UnityEvent
Decision rules
- Use SO events when designers need to wire connections in the inspector without code changes.
- Use C#
when performance matters (thousands of events/frame) and only programmers configure it.event Action - Use shared variable SOs over singletons for any data read by multiple systems (HP, score, settings).
- Use RuntimeSets over
— they're O(1) add/remove vs O(n) search.FindObjectsOfType - If an event carries complex data, create a typed SO event rather than passing multiple parameters.
- SO events survive scene loads if the asset is referenced by a persistent object or Addressable.
Output requirements
— complete C# class withScriptableObject Script
, fields, and methods[CreateAssetMenu]
— GameEventListener MonoBehaviour with registration lifecycleListener Script
— how to create assets, assign references, configure UnityEvent callbacksInspector Setup
— which systems produce events, which consume, data flow directionArchitecture Diagram
— why SO events over alternatives for this specific use caseTradeoff Notes
References
- Ryan Hipple — Game Architecture with ScriptableObjects (GDC 2017)
- Unity ScriptableObject Documentation
- CreateAssetMenu Attribute
- UnityEvent Documentation
Related skills
— general Unity patterns, lifecycle, and component architectureunity
— AI systems that consume SO events for perception/stimulusai-npc-behavior
— when events need network replication beyond local SO channelsmultiplayer-netcode
Failure handling
- If listeners don't receive events, verify
/OnEnable
registration and that the same SO asset instance is referenced (not a duplicate).OnDisable - If SO values reset between scenes, ensure the SO asset is not instantiated at runtime — reference the project asset directly.
- If UnityEvent callbacks show as "Missing", the target GameObject was destroyed — use
unregistration.OnDisable - If event ordering matters, document the expected order or use a priority field in the listener.