Applying the FSM Context Pattern to Scaling: The Reusable ScalarFSM

Applying the FSM Context Pattern to Scaling: The Reusable ScalarFSM

Leader posted 4 min read

Applying the FSM Context Pattern to Scaling: The Reusable ScalarFSM

In our previous article, we demonstrated how to eliminate Update() spaghetti by applying the FSM Context Pattern to complex Rotation logic. The result was a single, reusable blueprint ("RotationFSM") that drove three objects on different axes.

Here, we prove the true versatility of this pattern by applying it to Scale motion. The vast majority of the logic remains the same—only the Context data and the specific Unity functions change.

1. The Context: Swapping Angular for Linear Parameters

The core philosophy remains: isolate the specific data required for the motion. We move from the RotationContext to the ScaleContext.

Rotation Context Parameters Scale Context Parameters Purpose
RotationSpeed (float) ScaleSpeed (float) Linear speed of scale change.
RotationAxis (Vector3) ScaleAxis (Vector3) The axis (or axes) to apply the scale along.
MaxAngle / MinAngle MaxScale / MinScale The absolute min and max bounds for the object's local scale.

ScaleContext.cs: Data Encapsulation

The ScaleContext holds the new parameters and is what ultimately manipulates the TransformHandle.localScale.

public class ScaleContext : IStateContext
{
    // The new parameters that define scaling motion
    public float ScaleSpeed = 0.5f;
    public float MaxScale = 3.0f;
    public float MinScale = 0.5f;

    public Vector3 ScaleAxis;
    public Vector3 OriginalScale = Vector3.one;

    public Transform TransformHandle;
    // ...
}

2. The FSM Definition: Same Flow, New Names

The Finite State Machine flow is identical to the rotation demo (Move $\rightarrow$ Max $\rightarrow$ Move Back $\rightarrow$ Min) but uses domain-appropriate terminology.

The blueprint name changes from "RotationFSM" to "ScalarFSM".

Rotation FSM Scalar FSM (Change)
States: RotatingForward States: ScalingUp
States: RotatingBackward States: ScalingDown
Predicate: MaxReached Predicate: Apex
Predicate: MinReached Predicate: Root

The Core Logic (The Only Update)

Instead of applying a Quaternion update using Quaternion.AngleAxis, the state update logic now directly modifies the localScale vector using the ScaleAxis vector stored in the Context.

// The OnUpdateScalingUp function within ScaleContext.cs
private void OnUpdateScalingUp(IStateContext context)
{
    if (context is ScaleContext sc)
    {
        // Linearly increase the scale along the specified axis(es)
        Vector3 scaleDelta = sc.ScaleAxis * (sc.ScaleSpeed * Time.deltaTime);
        sc.TransformHandle.localScale += scaleDelta; // The only movement line!
    }
}

The elegance here is that the state engine (the FSM) required zero changes. We only updated the specific motion logic inside the state functions of the new ScaleContext.


3. The Entry Point: Demonstrating Multi-Axis Motion

The SimpleScalarDemoFSM.cs acts as the entry point. This demo highlights a capability easily solved with scaling that was slightly more complex with rotation: multi-axis movement.

Notice how the third instance utilizes a ScaleAxis vector with multiple components set to 1 to drive a single FSM instance to scale along both the X and Y axes simultaneously.

private void OnEnterExecuting(IStateContext context)
{
    if (context is SimpleScalarDemoFSM ssd)
    {
        float speed = 0.5f;
        float maxScale = 3f;
        float minScale = 0.5f;
        
        // 1. X-axis Scale
        ScaleContext xAxisContext = new ScaleContext(ssd.Xaxis, new Vector3(1, 0, 0), speed, maxScale, minScale);
        
        // 2. Y-axis Scale
        ScaleContext yAxisContext = new ScaleContext(ssd.Yaxis, new Vector3(0, 1, 0), speed, maxScale, minScale);
        
        // 3. XY-axis Scale: Scales on X and Y using the *same* FSM definition
        ScaleContext xyAxisContext = new ScaleContext(ssd.XYaxis, new Vector3(1, 1, 0), speed, maxScale, minScale);
        
        // ... Instantiate all handles and transition to start state
    }
}

This demo proves that the FSM Context Pattern is an engine-agnostic architectural solution. Once you define the pattern, reusing it for any kind of movement—Rotation, Scale, or Translation (coming next!)—is as simple as defining a new Context class.

See the demo in action:
YouTube Channel Video

Support the Vision and See the Code!

If this pattern has helped clean up your Update() loop, please consider supporting our development! Your support ensures we can continue to provide advanced, architectural solutions for cleaner game development.

Resources & Code:

The FSM Package (Unity Asset Store):
https://assetstore.unity.com/packages/slug/332450

NuGet Package (Non-Unity Core):
https://www.nuget.org/packages/TheSingularityWorkshop.FSM_API

GitHub Repository:
https://github.com/TrentBest/FSM_API

Support Our Work:

Patreon Page:
https://www.patreon.com/c/TheSingularityWorkshop

Support Us (PayPal Donation):
https://www.paypal.com/donate/?hosted_button_id=3Z7263LCQMV9J

We'd love to hear your thoughts! Please Like this post, Love the code, and Share your feedback in the comments.

A Hyper-Detailed, Architecturally Impossible Synthesis of Consciousness and Digital Matter. The image is a frenetic, deeply complex digital vista where a central Luminous Eye dominates a vast, glowing circuit landscape. This eye, suspended mid-air, is a sphere of intense, fractal energy—a pulsating vortex of pink, violet, and electric blue light—that powerfully suggests an emergence of digital consciousness or a Technological Singularity itself. The core is a bottomless black aperture, ringed by a white-hot plasma disc. Below this ocular energy source, the light dissipates into an intricate, copper-gold and neon-blue Circuit Board Megastructure that stretches to the horizon, impossibly dense with exaggerated microchips, glowing resistor arrays, and power conduits that form deep, glowing canyons. The background is a dark, holographic projection field displaying complex schematics, mathematical models, and flowing data streams, reinforcing the theme of Absolute Digital Engineering. The entire scene is bathed in a dramatic, opposing light source—a warm, orange-gold glow from the left and an ice-cold, electric-blue glow from the right—creating a maximalist, high-contrast visual experience that definitively rejects the minimalist simplicity of conventional design and announces: Technology is intricate, overwhelming, and infinitely complex.

If you read this far, tweet to the author to show them you care. Tweet a Thanks

1 Comment

0 votes

More Posts

The FSM Agent Architecture: Scaling NavMesh Agents with Decoupled Logic

The Singularity Workshop - Oct 15

The Grand Finale: Orchestrating Complex Motion with Multi-Context FSMs

The Singularity Workshop - Oct 15

Building a Reusable State Machine for Oscillating Rotation in Unity

The Singularity Workshop - Oct 14

Completing the Motion Trilogy: The Reusable TranslationFSM

The Singularity Workshop - Oct 14

When Unity Glitches, You Build Your Own Loop: The Four-Line App Core

The Singularity Workshop - Oct 17
chevron_left