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.

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:
CheckCanOperate() — validates that the required pointers and state are validHandleMovement() — calculates and applies movement (no-op in base)HandleRotation() — calculates and applies rotation (no-op in base)
Key Fields
| Field | Description |
|---|
m_moveModeName | Mode string this mover activates for (set in Activate()) |
m_rotateModeName | Mode string this mover’s rotation activates for |
movementActive / rotationActive | Whether movement/rotation processing is currently running |
delta | Cached frame delta time |
activeProfile | Pointer to current GS_UnitMovementProfile (updated via MovementProfileChanged) |
debugForceTick | If 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
| Component | Mode Name | Description |
|---|
| 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
| Bus | Event | Description |
|---|
MoverContextNotificationBus | MovementModeChanged(modeName) | Activates or deactivates movement processing based on mode name match. |
MoverContextNotificationBus | RotationModeChanged(modeName) | Activates or deactivates rotation processing based on mode name match. |
MoverContextNotificationBus | ContextStateChanged(stateName, value) | Allows movers to react to state flags (e.g. "StopMovement"). |
MoverContextNotificationBus | MovementProfileChanged(profile*) | Updates the cached activeProfile pointer. |
Virtual Methods
Override these when extending any mover:
| Method | Parameters | Returns | Description |
|---|
ToggleMovement | bool on | void | Called when the movement mode activates or deactivates. |
ToggleRotation | bool on | void | Called when the rotation mode activates or deactivates. |
HandleMovement | — | void | Called each tick when movement is active. Override to implement movement logic. |
HandleRotation | — | void | Called each tick when rotation is active. Override to implement rotation logic. |
CheckCanOperate | — | bool | Returns 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.

Contents
How It Works
HandleMovement()
Called each post-physics tick while movement mode is "Free":
- Reads
groundedMoveInput pointer from MoverContextRequestBus::GetGroundMoveInputAxis. - If
EnableSlopeSlowdown is true, attenuates the input vector on steep slopes (see Slope Slowdown). - Multiplies the attenuated direction by
CalculateSpeed() to get destinationVelocity. - Fetches
rigidBody->GetLinearVelocity() as the current velocity. - Calls
GS_Core::Springs::AccelerationSpringDamper(position, velocity, cachedAcceleration, destinationVelocity, moveHalflife, delta). - 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()
- Reads
groundedMoveInput from the MoverContext. - Updates
lastDirection only when groundedMoveInput is non-zero — so the unit keeps facing the last direction when stopped. - Computes target yaw from
lastDirection using atan2f. - Calls
GS_Core::Springs::QuaternionSpringDamper(currentRotation, cachedAngularVelocity, targetRotation, rotateHalflife, delta). - 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
| Field | Default | Description |
|---|
moveHalflife | 0.1 | Spring halflife for movement velocity. Smaller = snappier acceleration. |
rotateHalflife | 0.2 | Spring halflife for rotation. Smaller = faster turn response. |
EnableSlopeSlowdown | true | Whether steep slopes reduce movement speed. |
uphillSlowStrength | 0.5 | Maximum speed reduction factor at the max walkable angle (0 = no reduction, 1 = full stop). |
uphillSlowExponent | 2.5 | Curve shape of the slowdown ramp. Higher = slower onset, steeper drop near max. |
startSlowAngle | 30° | 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.

Contents
How It Works
HandleMovement()
Called each post-physics tick while movement mode is "Slide":
- Reads
slopeDir from MoverContextRequestBus::GetSlopeDirection. - Computes
destinationVelocity = slopeDir * baseSlideSpeed. - 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. - Fetches
rigidBody->GetLinearVelocity() as the current velocity. - Calls
GS_Core::Springs::AccelerationSpringDamper(position, velocity, cachedAcceleration, destinationVelocity, moveHalflife, delta). - Applies the result:
rigidBody->SetLinearVelocity(velocity). - Calls
FinishSliding() to check whether the slide should end.
HandleRotation()
- Reads
slopeDir from the MoverContext. - Computes target yaw from slope direction using
atan2f — unit faces down the slope. - Calls
GS_Core::Springs::QuaternionSpringDamper(currentRotation, cachedAngularVelocity, targetRotation, rotateHalflife, delta). - 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
| Field | Default | Description |
|---|
moveHalflife | 0.1 | Spring halflife for slide velocity. |
rotateHalflife | 0.15 | Spring halflife for rotation toward slope direction. |
baseSlideSpeed | 8.0 | Target speed along the slope direction (m/s). |
EnableInputSlideResistance | true | Whether player input can partially resist or redirect the slide. |
InputResistanceInfluence | 2.0 | Scalar applied to groundedMoveInput when computing resistance. Higher = more player control. |
minSlideAngle | 20° | Slope angle below which the unit may recover (if also slow enough). |
minSpeedToStop | 1.5 | Speed 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
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.