Action Runners¶
Run actions at specific moments - on start, every frame, on collision, on destroy - with zero-overhead dedicated components.
Each action runner is a small, focused component that hooks into exactly one Unity callback. Want something to happen every frame? Add an Update runner. Need initialization logic? Add a Start runner. Need to react to collisions? Add a Physics Event runner. There are no runtime checks and no conditional branching - each component fires its actions directly from the callback it is named after. If you need multiple lifecycle events, add multiple components.
Available Components¶
Update Loop Runners¶
| Component | Executes On | Use Case |
|---|---|---|
OnUpdateActionRunner |
Update() |
Per-frame logic, UI updates |
OnFixedUpdateActionRunner |
FixedUpdate() |
Physics calculations |
OnLateUpdateActionRunner |
LateUpdate() |
Camera follow, final adjustments |
Performance
Zero overhead - direct execution, no runtime checks.
Lifecycle Event Runners¶
| Component | Executes On | Use Case |
|---|---|---|
OnAwakeActionRunner |
Awake() |
Component initialization |
OnStartActionRunner |
Start() |
Start initialization (after Awake) |
OnEnableActionRunner |
OnEnable() |
Activate effects, subscribe to events |
OnDisableActionRunner |
OnDisable() |
Deactivate effects, unsubscribe |
OnDestroyActionRunner |
OnDestroy() |
Cleanup, release resources |
Performance
Zero overhead - direct execution, no runtime checks.
Physics Event Runner¶
| Component | Executes On | Use Case |
|---|---|---|
PhysicsEventActionRunner |
Collision / Trigger events | Interactive objects, trigger zones |
Features:
- Both 3D and 2D physics events
- Layer mask filtering
- Tag filtering
- Event-driven (zero cost when no collisions)
Performance
Event-driven - only executes when physics events occur.
Conditional Execution¶
| Component | Type | Use Case |
|---|---|---|
ConditionalAction |
Action (NOT MonoBehaviour) | State-based execution |
ConditionalAction is not a component
ConditionalAction is a regular action that wraps other actions with conditions. Use it inside other action runners, not as a standalone component.
GameObject
OnUpdateActionRunner
actions:
ConditionalAction
conditions: [DistanceCondition, HealthCondition]
actions: [PlayWarningSound, ShowUI]
Usage Patterns¶
Single Event¶
Best for simple, focused behavior.
Multiple Events¶
GameObject
OnStartActionRunner (initialization)
OnUpdateActionRunner (movement)
OnDestroyActionRunner (cleanup)
Best for complex objects needing different lifecycle stages.
Conditional Logic¶
GameObject
OnUpdateActionRunner
actions:
ConditionalAction (if health low)
actions: [ShowWarning]
ConditionalAction (if player near)
actions: [LookAtPlayer]
Best for state-driven behavior without separate MonoBehaviours.
Physics Interactions¶
GameObject
PhysicsEventActionRunner
layerFilter: PlayerLayer
onTriggerEnterActions: [OpenDoor, PlaySound]
Best for trigger zones and collision responses.
Performance Comparison¶
| Pattern | Overhead | Memory | Recommendation |
|---|---|---|---|
| Specialized Runners | None | Minimal | Always use |
| ConditionalAction | Per-execution | Minimal | Use for state logic |
| PhysicsEventActionRunner | Event-driven | Small | Use for physics |
All patterns are efficient. There are no bad choices here.
Best Practices¶
Use specialized components¶
Clear, explicit, zero overhead.
Use ConditionalAction for state logic¶
Avoids executing actions when conditions are not met.
Combine multiple specialized runners¶
GameObject
OnAwakeActionRunner (setup)
OnEnableActionRunner (activate)
OnUpdateActionRunner (tick)
OnDisableActionRunner (deactivate)
PhysicsEventActionRunner (collisions)
Each component has a clear, single purpose.
Use PhysicsEventActionRunner for physics¶
Event-driven, zero per-frame cost.
Do not poll for physics in Update
Checking for collisions inside an OnUpdateActionRunner is expensive and unnecessary. Use PhysicsEventActionRunner instead - it is event-driven and only runs when physics events actually occur.
Summary¶
The action runner architecture is intentionally simple:
- Specialized runners for each Unity callback (
Update,FixedUpdate,Awake, etc.) - ConditionalAction for state-based logic (regular action, not MonoBehaviour)
- PhysicsEventActionRunner for collision/trigger events
Each component does one thing with zero overhead. Combine them as needed.
Prefer composition over configuration
Add the specific components you need rather than configuring one component to do multiple things.