logo SERENITY
Game Systems Foundation
Search Results for

    Show / Hide Table of Contents

    Class ProceduralAnimatorSimulator

    Drives a live ProceduralAnimatorComponent pipeline against a hidden preview instance of a model, so the Animation Hub can play, scrub and poke at a profile's rules/layers/actions without ever entering Play mode or touching the user's scene. Owns a Serenity.Global.Infrastructure.Editor.Preview.SerenityModelPreviewSession (the hidden instance) and an Serenity.Global.Infrastructure.Editor.Preview.EditorPlaybackClock (the simulated time source); every write this class makes lands on Serenity.Global.Infrastructure.Editor.Preview.SerenityModelPreviewSession.InstanceRoot or its own transient dictionaries — nothing is serialized, nothing is dirtied, and no asset is ever touched.

    Inheritance
    object
    ProceduralAnimatorSimulator
    Implements
    IDisposable
    Inherited Members
    object.ToString()
    object.Equals(object)
    object.Equals(object, object)
    object.ReferenceEquals(object, object)
    object.GetHashCode()
    object.GetType()
    Namespace: Serenity.Editor.AnimationHub.Gui
    Assembly: Serenity.AnimationHub.Editor.dll
    Syntax
    public sealed class ProceduralAnimatorSimulator : IDisposable
    Remarks

    Noise/Perlin layers seed their phase from wall-clock/session state, so replaying the same session twice will not reproduce an identical pose — accepted for a visual preview, not a regression tool. Ticking also mutates non-serialized transient fields (cooldown timers, action runtime state) directly on the shared layer/rule/action UnityEngine.ScriptableObject assets the profile references, exactly as a real runtime instance would; those fields are never serialized so nothing about the asset on disk changes. Every Bind(GameObject) re-initializes the animator, which calls Condition.Reset() on every rule's condition tree — the simulator's own "Play" therefore always starts rule evaluation from a clean slate, the same way a fresh scene load would.

    Constructors

    ProceduralAnimatorSimulator(Action)

    Declaration
    public ProceduralAnimatorSimulator(Action repaintRequested)
    Parameters
    Type Name Description
    Action repaintRequested

    Fields

    DefaultPulseDurationSeconds

    Duration of a "Pulse" button replay — matches the traversal-length pulses gameplay controllers like RailShooter's EnemyBehaviorController write onto their state keys.

    Declaration
    public const float DefaultPulseDurationSeconds = 1.2
    Field Value
    Type Description
    float

    Properties

    IsBound

    Declaration
    public bool IsBound { get; }
    Property Value
    Type Description
    bool

    IsPlaying

    Declaration
    public bool IsPlaying { get; }
    Property Value
    Type Description
    bool

    Session

    Declaration
    public SerenityModelPreviewSession Session { get; }
    Property Value
    Type Description
    SerenityModelPreviewSession

    The owned preview session, or null before the first successful Bind(GameObject).

    SimulatedTime

    Declaration
    public float SimulatedTime { get; }
    Property Value
    Type Description
    float

    StateKeys

    Declaration
    public IReadOnlyList<ProceduralStateKeyBinding> StateKeys { get; }
    Property Value
    Type Description
    IReadOnlyList<ProceduralStateKeyBinding>

    StatusText

    Declaration
    public string StatusText { get; }
    Property Value
    Type Description
    string

    Methods

    AdvancePulses(float)

    Writes every active pulse's current value onto its state key, at time, so the slider visually tracks the replayed arc; a pulse that has finished writes its binding's MinValue (gameplay pulses always end back at zero) and is removed. Runs at the top of every internal tick so it stays in lockstep with whatever advances SimulatedTime — the playing clock, a paused StepOnce(), or a paused SetStateValue(UnityStateKey, float) re-tick. Public so tests can drive pulse advancement directly without pumping EditorApplication.update.

    Declaration
    public void AdvancePulses(float time)
    Parameters
    Type Name Description
    float time

    Bind(GameObject)

    Binds the simulator to modelPrefabAsset: creates a hidden preview instance, resolves its Procedural Animator components, and runs one static first frame. A no-op when modelPrefabAsset is reference-equal to whatever was last requested — a caller drawing every repaint (like the GUI layer) can call this unconditionally. Every failure tears down whatever was created and leaves StatusText explaining why; it never throws and never shows a dialog.

    Declaration
    public void Bind(GameObject modelPrefabAsset)
    Parameters
    Type Name Description
    GameObject modelPrefabAsset

    Dispose()

    Declaration
    public void Dispose()

    GetStateValue(UnityStateKey)

    Declaration
    public float GetStateValue(UnityStateKey key)
    Parameters
    Type Name Description
    UnityStateKey key
    Returns
    Type Description
    float

    HasActivePulse(UnityStateKey)

    Declaration
    public bool HasActivePulse(UnityStateKey key)
    Parameters
    Type Name Description
    UnityStateKey key
    Returns
    Type Description
    bool

    Pause()

    Declaration
    public void Pause()

    Play()

    Declaration
    public void Play()

    RequestRepaint()

    Requests a repaint of the hosting window — exposed so ProceduralAnimatorSimulatorGui can drive a repaint from GUI-level input (viewport orbit drag/scroll) without this class exposing its private repaint callback field directly.

    Declaration
    public void RequestRepaint()

    ResetSimulation()

    Rewinds simulated time to zero, stops every active action, zeroes every layer weight, re-seeds state keys back to their minimum, and runs one static frame — the same clean-slate shape as a fresh Bind(GameObject), without re-instantiating the preview object.

    Declaration
    public void ResetSimulation()

    SetStateValue(UnityStateKey, float)

    Declaration
    public void SetStateValue(UnityStateKey key, float value)
    Parameters
    Type Name Description
    UnityStateKey key
    float value

    StartPulseAndPlay(UnityStateKey, float)

    Replays a StateKeyPulse on key starting at the current simulated time: a no-op unless bound and key is one of StateKeys. Advancing time is required for the pulse to play out, so this ensures the clock is playing first — if Play() refuses (e.g. entering Play Mode, which sets StatusText itself), the pulse is dropped rather than started against a frozen clock. Overwrites any pulse already running on the same key.

    Declaration
    public void StartPulseAndPlay(UnityStateKey key, float durationSeconds = 1.2)
    Parameters
    Type Name Description
    UnityStateKey key
    float durationSeconds

    StepOnce()

    Advances the simulation by one fixed 1/60s step. No-op while playing — stepping is a paused-only affordance, the play/step buttons already reflect this.

    Declaration
    public void StepOnce()

    TogglePlay()

    Declaration
    public void TogglePlay()

    Unbind()

    Releases the preview session, stops the clock, and clears every resolved reference. Safe to call repeatedly (idempotent) and a subsequent Bind(GameObject) — even to the same asset — rebinds from scratch.

    Declaration
    public void Unbind()

    Implements

    IDisposable
    In this article
    © 2026 Serenity. All Rights Reserved