Skip to content

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

GameObject
  OnUpdateActionRunner
    actions: [MoveForward, Rotate]

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

GameObject
  OnStartActionRunner
  OnUpdateActionRunner

Clear, explicit, zero overhead.


Use ConditionalAction for state logic

OnUpdateActionRunner
  ConditionalAction
    conditions: [IsAlive, HasTarget]
    actions: [Attack]

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

PhysicsEventActionRunner
  onTriggerEnterActions: [...]

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:

  1. Specialized runners for each Unity callback (Update, FixedUpdate, Awake, etc.)
  2. ConditionalAction for state-based logic (regular action, not MonoBehaviour)
  3. 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.