This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

Movers

Mover base class and concrete mover components — translate MoverContext input into physics-based unit motion via named mode activation.

Movers translate the processed movement input from the MoverContext into physics forces on the unit’s rigid body. Each mover activates for a specific named mode — when the MoverContext broadcasts MovementModeChanged("Free"), only the mover whose m_moveModeName matches "Free" activates. All others deactivate. This makes the locomotion system fully mode-driven and composable.

For usage guides and setup examples, see The Basics: GS_Unit.

Mover component in the O3DE Inspector

 

Contents


Class Hierarchy

GS_MoverComponent (base — mode-aware activation, tick management)
  └── GS_PhysicsMoverComponent (adds RigidBody cache + validity check)
        ├── GS_3DFreeMoverComponent    (mode: "Free")
        └── GS_3DSlideMoverComponent   (mode: "Slide")

GS_MoverComponent (Base)

Tick: AzPhysics::SystemEvents::OnPostSimulateEvent (after the physics step). Optional debugForceTick uses AZ::TickBus for debugging without physics.

Mode-Aware Activation

Listens to MoverContextNotificationBus::MovementModeChanged and RotationModeChanged. Compares the broadcast mode name against its own m_moveModeName and m_rotateModeName. Calls ToggleMovement(true/false) and ToggleRotation(true/false) accordingly. The physics post-simulate handler is only registered when the mover is active, saving ticks when inactive.

Per-Tick Processing

Each tick:

  1. CheckCanOperate() — validates that the required pointers and state are valid
  2. HandleMovement() — calculates and applies movement (no-op in base)
  3. HandleRotation() — calculates and applies rotation (no-op in base)

Key Fields

FieldDescription
m_moveModeNameMode string this mover activates for (set in Activate())
m_rotateModeNameMode string this mover’s rotation activates for
movementActive / rotationActiveWhether movement/rotation processing is currently running
deltaCached frame delta time
activeProfilePointer to current GS_UnitMovementProfile (updated via MovementProfileChanged)
debugForceTickIf true, uses game tick instead of post-simulate (for debugging without physics)

GS_PhysicsMoverComponent

Extends GS_MoverComponent. On activate, fetches AzPhysics::RigidBody* from the entity. CheckCanOperate() verifies the rigid body pointer is valid before allowing tick processing.


Concrete Movers

ComponentMode NameDescription
GS_3DFreeMoverComponent"Free"Standard 3D locomotion — camera-relative, spring-damped velocity and rotation
GS_3DSlideMoverComponent"Slide"Slope-sliding locomotion — activated by the grounder when slope exceeds maxWalkAngle

API Reference

Movers consume two buses and produce one:

Consumed

BusEventDescription
MoverContextNotificationBusMovementModeChanged(modeName)Activates or deactivates movement processing based on mode name match.
MoverContextNotificationBusRotationModeChanged(modeName)Activates or deactivates rotation processing based on mode name match.
MoverContextNotificationBusContextStateChanged(stateName, value)Allows movers to react to state flags (e.g. "StopMovement").
MoverContextNotificationBusMovementProfileChanged(profile*)Updates the cached activeProfile pointer.

Virtual Methods

Override these when extending any mover:

MethodParametersReturnsDescription
ToggleMovementbool onvoidCalled when the movement mode activates or deactivates.
ToggleRotationbool onvoidCalled when the rotation mode activates or deactivates.
HandleMovementvoidCalled each tick when movement is active. Override to implement movement logic.
HandleRotationvoidCalled each tick when rotation is active. Override to implement rotation logic.
CheckCanOperateboolReturns true if the mover has everything it needs to run this tick.

Extension Guide

Use the Mover ClassWizard template to generate a new mover with boilerplate already in place — see GS_Unit Templates. The template offers two base class options: Physics Mover (default) for rigid-body locomotion, and Base Mover for transform-only movement.

Extend GS_PhysicsMoverComponent to create a custom physics-driven mover.

#pragma once
#include <Source/Unit/Mover/GS_PhysicsMoverComponent.h>

namespace MyProject
{
    class MyCustomMover : public GS_Unit::GS_PhysicsMoverComponent
    {
    public:
        AZ_COMPONENT_DECL(MyCustomMover);
        static void Reflect(AZ::ReflectContext* context);

    protected:
        void Activate() override;

        void HandleMovement() override;
        void HandleRotation() override;

    private:
        // Mode name must be set in Activate():
        // m_moveModeName = "MyMode";
        // m_rotateModeName = "MyMode";
    };
}

In HandleMovement(), read from the MoverContext and write to the rigid body:

void MyCustomMover::HandleMovement()
{
    AZ::Vector3* groundedInput = nullptr;
    GS_Unit::MoverContextRequestBus::EventResult(
        groundedInput, GetEntityId(),
        &GS_Unit::MoverContextRequestBus::Events::GetGroundMoveInputAxis
    );

    if (!groundedInput || groundedInput->IsZero()) return;

    AZ::Vector3 targetVelocity = *groundedInput * activeProfile->moveSpeed;
    m_rigidBody->SetLinearVelocity(targetVelocity);
}

See Also


Get GS_Unit

GS_Unit — Explore this gem on the product page and add it to your project.

1 - 3D Free Mover

Standard 3D locomotion — camera-relative movement and rotation driven by spring-damped physics, with optional slope slowdown.

GS_3DFreeMoverComponent is the standard mover for walking characters. It reads the ground-projected input vector from the MoverContext, applies optional slope attenuation, computes a destination velocity, and drives the rigid body via AccelerationSpringDamper. Rotation is handled separately using QuaternionSpringDamper to face the last non-zero movement direction.

Mode names: "Free" (both movement and rotation)

For usage guides and setup examples, see The Basics: GS_Unit.

Mover component in the O3DE Inspector

 

Contents


How It Works

HandleMovement()

Called each post-physics tick while movement mode is "Free":

  1. Reads groundedMoveInput pointer from MoverContextRequestBus::GetGroundMoveInputAxis.
  2. If EnableSlopeSlowdown is true, attenuates the input vector on steep slopes (see Slope Slowdown).
  3. Multiplies the attenuated direction by CalculateSpeed() to get destinationVelocity.
  4. Fetches rigidBody->GetLinearVelocity() as the current velocity.
  5. Calls GS_Core::Springs::AccelerationSpringDamper(position, velocity, cachedAcceleration, destinationVelocity, moveHalflife, delta).
  6. Applies the result: rigidBody->SetLinearVelocity(velocity).

The cachedAcceleration is a member field that persists between frames to produce smooth acceleration response even on sudden direction changes.

HandleRotation()

  1. Reads groundedMoveInput from the MoverContext.
  2. Updates lastDirection only when groundedMoveInput is non-zero — so the unit keeps facing the last direction when stopped.
  3. Computes target yaw from lastDirection using atan2f.
  4. Calls GS_Core::Springs::QuaternionSpringDamper(currentRotation, cachedAngularVelocity, targetRotation, rotateHalflife, delta).
  5. Applies cachedAngularVelocity.Z to rigidBody->SetAngularVelocity().

StopMovement State

When ContextStateChanged("StopMovement", 1) fires, the mover zeros both velocity and cached acceleration, then clears the state back to 0. This allows other systems (e.g. landing from a jump, ability wind-up) to cleanly halt the unit.


Slope Slowdown

When EnableSlopeSlowdown is true, the mover reduces movement speed as the slope angle increases toward maxWalkAngle. The attenuation curve uses an exponent applied to the dot product of the movement direction against the uphill slope direction:

attenuation = 1.0 - uphillSlowStrength * pow(dot(moveDir, slopeDir), uphillSlowExponent)
              × remap(slopeAngle, startSlowAngle, maxWalkAngle, 0, 1)

The slowdown begins at startSlowAngle degrees and reaches maximum reduction at maxWalkAngle. At or beyond maxWalkAngle, the grounder will switch the unit to "Slide" mode regardless.


Speed Calculation

CalculateSpeed() lerps curSpeed toward activeProfile->moveSpeed each frame:

curSpeed = AZ::Lerp(curSpeed, activeProfile->moveSpeed, expf(-speedChangeSmoothing * delta));

speedChangeSmoothing is read from activeProfile. This produces a smooth speed transition when the movement profile changes (e.g. entering a slow zone).


Editor-Exposed Settings

FieldDefaultDescription
moveHalflife0.1Spring halflife for movement velocity. Smaller = snappier acceleration.
rotateHalflife0.2Spring halflife for rotation. Smaller = faster turn response.
EnableSlopeSlowdowntrueWhether steep slopes reduce movement speed.
uphillSlowStrength0.5Maximum speed reduction factor at the max walkable angle (0 = no reduction, 1 = full stop).
uphillSlowExponent2.5Curve shape of the slowdown ramp. Higher = slower onset, steeper drop near max.
startSlowAngle30°Slope angle at which slowdown begins.

Extension Guide

Extend GS_3DFreeMoverComponent to override movement or rotation behavior while keeping the base spring physics.

#pragma once
#include <Source/Unit/Mover/GS_3DFreeMoverComponent.h>

namespace MyProject
{
    class MyFreeMove : public GS_Unit::GS_3DFreeMoverComponent
    {
    public:
        AZ_COMPONENT_DECL(MyFreeMove);
        static void Reflect(AZ::ReflectContext* context);

    protected:
        void HandleMovement() override;
    };
}
void MyFreeMove::HandleMovement()
{
    // Call base for standard spring movement
    GS_3DFreeMoverComponent::HandleMovement();

    // Add custom post-processing (e.g. strafe penalty, footstep IK correction)
}

See Also


Get GS_Unit

GS_Unit — Explore this gem on the product page and add it to your project.

2 - Slide Mover

Slope-sliding locomotion — automatically activated when slope exceeds maxWalkAngle, drives the unit down the slope via spring-damped physics with optional input resistance and automatic recovery.

GS_3DSlideMoverComponent handles slope-sliding locomotion. It activates automatically when the grounder detects a slope angle exceeding maxWalkAngle, and deactivates when the slope eases or the unit slows enough to recover.

Mode names: "Slide" (both movement and rotation)

For usage guides and setup examples, see The Basics: GS_Unit.

Mover component in the O3DE Inspector

 

Contents


How It Works

HandleMovement()

Called each post-physics tick while movement mode is "Slide":

  1. Reads slopeDir from MoverContextRequestBus::GetSlopeDirection.
  2. Computes destinationVelocity = slopeDir * baseSlideSpeed.
  3. If EnableInputSlideResistance is true, reads groundedMoveInput and applies an opposing influence:
    destinationVelocity += groundedMoveInput * InputResistanceInfluence
    
    This allows the player to push slightly against or across the slide direction.
  4. Fetches rigidBody->GetLinearVelocity() as the current velocity.
  5. Calls GS_Core::Springs::AccelerationSpringDamper(position, velocity, cachedAcceleration, destinationVelocity, moveHalflife, delta).
  6. Applies the result: rigidBody->SetLinearVelocity(velocity).
  7. Calls FinishSliding() to check whether the slide should end.

HandleRotation()

  1. Reads slopeDir from the MoverContext.
  2. Computes target yaw from slope direction using atan2f — unit faces down the slope.
  3. Calls GS_Core::Springs::QuaternionSpringDamper(currentRotation, cachedAngularVelocity, targetRotation, rotateHalflife, delta).
  4. Applies cachedAngularVelocity.Z to rigidBody->SetAngularVelocity().

Finish Sliding

FinishSliding() is called every movement tick. It returns true and triggers recovery when both conditions are met:

  • The current slope angle is below minSlideAngle
  • The unit’s current speed is below minSpeedToStop

On recovery:

MoverContextRequestBus::ChangeMovementMode(recoveryMoveMode);
MoverContextRequestBus::ChangeRotationMode(recoveryRotateMode);

Both modes default to "Free", returning the unit to standard locomotion.


Editor-Exposed Settings

FieldDefaultDescription
moveHalflife0.1Spring halflife for slide velocity.
rotateHalflife0.15Spring halflife for rotation toward slope direction.
baseSlideSpeed8.0Target speed along the slope direction (m/s).
EnableInputSlideResistancetrueWhether player input can partially resist or redirect the slide.
InputResistanceInfluence2.0Scalar applied to groundedMoveInput when computing resistance. Higher = more player control.
minSlideAngle20°Slope angle below which the unit may recover (if also slow enough).
minSpeedToStop1.5Speed threshold below which the unit may recover (if also on shallow slope).
recoveryMoveMode"Free"Movement mode to switch to on recovery.
recoveryRotateMode"Free"Rotation mode to switch to on recovery.

Extension Guide

Extend GS_3DSlideMoverComponent to override slide behavior while keeping the base spring physics and recovery logic.

#pragma once
#include <Source/Unit/Mover/GS_3DSlideMoverComponent.h>

namespace MyProject
{
    class MySlide : public GS_Unit::GS_3DSlideMoverComponent
    {
    public:
        AZ_COMPONENT_DECL(MySlide);
        static void Reflect(AZ::ReflectContext* context);

    protected:
        void HandleMovement() override;
    };
}
void MySlide::HandleMovement()
{
    // Call base for standard slope physics
    GS_3DSlideMoverComponent::HandleMovement();

    // Add custom post-processing (e.g. audio trigger, particle effect on slide)
}

See Also

  • Movers — Mover base class and class hierarchy
  • GS_3DFreeMoverComponent — Standard free-locomotion mover
  • Mover Context — Provides slopeDir, groundedMoveInput, and mode switching
  • Grounders — Detect slope angle and trigger the switch to Slide mode
  • Springs UtilityAccelerationSpringDamper and QuaternionSpringDamper used internally

Get GS_Unit

GS_Unit — Explore this gem on the product page and add it to your project.

3 - 3D Strafe Mover

Aim-relative strafing movement for first-person and third-person units. Not yet implemented.

The 3D Strafe Mover provides aim-relative movement where the unit strafes relative to its facing direction. This is the standard movement model for first-person and third-person shooters where the camera or aim direction determines the movement frame.

This component is not yet implemented. This page will be updated with full API reference and usage documentation when the component is available.

For usage guides and setup examples, see The Basics: GS_Unit.


See Also


Get GS_Unit

GS_Unit — Explore this gem on the product page and add it to your project.

4 - Side Scroller Mover

2D side-scrolling movement constrained to a horizontal plane. Not yet implemented.

The Side Scroller Mover provides two-dimensional movement constrained to a horizontal plane with vertical jump support. This is the standard movement model for side-scrolling platformers, beat-em-ups, and other 2D gameplay projected in a 3D environment.

This component is not yet implemented. This page will be updated with full API reference and usage documentation when the component is available.

For usage guides and setup examples, see The Basics: GS_Unit.


See Also

  • Movement – Movement subsystem overview
  • Movers – All available mover components

Get GS_Unit

GS_Unit — Explore this gem on the product page and add it to your project.

5 - Grid Step Mover

Tile-based grid movement for turn-based or grid-locked unit locomotion. Not yet implemented.

The Grid Step Mover provides discrete, tile-based movement for units that move in fixed steps along a grid. This is the standard movement model for turn-based RPGs, tactics games, puzzle games, and any project that uses grid-locked locomotion.

This component is not yet implemented. This page will be updated with full API reference and usage documentation when the component is available.

For usage guides and setup examples, see The Basics: GS_Unit.


See Also

  • Movement – Movement subsystem overview
  • Movers – All available mover components

Get GS_Unit

GS_Unit — Explore this gem on the product page and add it to your project.