Playables

This page covers the playable system's architecture and how to create custom playable types.

Playable Architecture

The playable system is built around three concepts:

  1. Playable Entries: Database entries that define what should happen (play an animation, spawn a VFX, etc.).

  2. PlayableExecutor: The runtime engine that processes playable entries and executes them.

  3. PlayableEntity: Scene components that link GameObjects to the playable system.

Execution Flow

When a playable is triggered (by an ability, interaction, trigger, etc.):

  1. The PlayableExecutor receives the playable entry and an execution context.

  2. It reads the entry's configuration.

  3. It resolves targets (who/what is affected).

  4. It executes the action (play animation, spawn object, play sound, etc.).

  5. It handles timing (duration, speed curves, delays).

PlayableExecutionContext

The execution context carries information about who triggered the playable and who the targets are:

Built-in Playable Types

Each playable type handles a specific action:

Type
Entry Class
Purpose

Animation

PlayableAnimationEntry

Play character animations with blend, speed, and locking

Sound

PlayableSoundEntry

Play audio clips with volume, pitch, and spatial settings

Transform

PlayableTransformEntry

Move, rotate, or scale objects over time

Coordinates

PlayableCoordinatesEntry

Move entities to specific world positions

GameObject

PlayableGameObjectEntry

Show, hide, spawn, or destroy GameObjects

Camera Override

PlayableCameraOverrideEntry

Temporarily switch to a different camera

Creating Custom Playable Types

To add a new playable type:

Step 1: Create the Entry

Define a database entry for your playable type:

Step 2: Create the Executor Logic

Implement the logic that runs when this playable type is executed. This typically involves a coroutine or tween:

Step 3: Register with the Executor

Register your playable type handler so the PlayableExecutor knows how to run it.

Playable Entities and Overrides

PlayableEntity is a MonoBehaviour that marks a GameObject as participating in the playable system. It's the bridge between scene objects and playable entries.

PlayableTransformEntity extends this for transform playables, providing per-entity transform override support.

PlayableTransformEntryOverride lets you override transform playable settings per entity. For example, the same "weapon swing" animation might need different offsets for different character models.

PlayableAudioSource is a component that acts as a spatial audio source for sound playables.

CameraOverrideEntity is attached to camera objects that can be activated by camera override playables.

Animation Integration

PlayableAnimationTracker

Tracks currently playing animations on an entity. Used to prevent conflicts (two animations trying to play on the same layer simultaneously).

PlayableAnimationTargeting

Resolves which animator and which layers an animation playable should affect, based on the entity's configuration.

AnimationSpeedCurveController

Applies speed curves to animations. This lets you speed up or slow down parts of an animation (e.g., a fast swing with a slow followthrough).

AnimationLockEvents

Events that fire when animation locks start and end. An animation lock prevents other animations from playing and can prevent player input.

  • AnimationLockStartedEvent: An animation lock began.

  • AnimationLockEndedEvent: An animation lock ended.

PlayableCoroutineHelper

A utility for running playable coroutines outside of MonoBehaviours. Since playables may be triggered from non-MonoBehaviour code (plugins, command handlers), this helper manages coroutine execution.

Best Practices

  • Keep playable entries focused on a single action. Combine multiple playables in a PlayableConfiguration for sequences.

  • Use speed curves for polish. They make animations feel much more dynamic.

  • Always handle null cases (missing cameras, missing animators, missing audio sources).

  • Test playables in isolation before combining them in configurations.

  • Use PlayableTransformEntryOverride when the same playable needs to work on characters with different proportions.

Last updated

Was this helpful?