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.