Appearance
How to customize Motion movement behavior
Practical examples of frequently requested modifications to Motion's movement system.
Behavior-defining defaults live on component profile assets. For project tuning, duplicate the assigned Motion profile into your project content, edit the duplicate, and assign it back to the component's Profile property. See Component profiles for the complete profile workflow.
Use the section that matches the behavior you need. Each recipe stands on its own.
Adding Stamina Drain to Sprint
Motion's sprint component includes built-in stamina support. Here's how to enable and customize it.
Enable Stamina System
- Duplicate the assigned sprint profile.
- Set
bUseStaminaSystem = true. - Configure stamina thresholds:
| Property | Description | Shipped default |
|---|---|---|
MinStaminaToSprint | Stamina needed to START | 1.5 |
MinStaminaToStopSprinting | Stamina to CONTINUE (hysteresis) | 0.25 |
RegenDelayDuration | Seconds before regen after exhaustion | 2.0 |
Configure Stamina Effects
Assign these GameplayEffects on the sprint profile:
SprintStaminaDrainEffect = GE_Motion_SprintStaminaDrain
StaminaRegenEffect = GE_Motion_SprintStaminaRegen
StaminaRegenDelayEffect = GE_Motion_SprintStaminaRegenDelayCustom Drain Rate
Create a custom GameplayEffect Blueprint:
- Duplicate
GE_Motion_SprintStaminaDrain - Modify the periodic effect magnitude
- Assign your custom effect to the sprint profile
Blueprint: React to Exhaustion
text
Event OnSprintStaminaDepletedDelegate
├── Play Sound (Exhaustion_SFX)
├── Play Camera Shake (Exhaustion_Shake)
└── Show UI WarningModifying Jump Behavior
Add Multi-Jump
Duplicate the assigned jump profile, then:
- Set
MaxAdditionalJumps = 1for double jump, or more for triple jump. - Optionally set
AdditionalJumpVelocityMultiplier = 0.8, or lower for weaker subsequent jumps.
Adjust Jump Height
Method 1: Jump profile values
JumpVelocityMultiplier = 1.2 // Multiply base jump velocity by 1.2
// OR
JumpVelocityModifier = 200.0 // Add 200 units to jump velocityMotionJumpComponent does not read the JumpVelocity attribute when performing a jump. It derives CharacterMovementComponent->JumpZVelocity from the value cached at initialization plus the assigned profile's multiplier and modifier, so use the profile values for the built-in jump path.
Add Coyote Time
On the assigned jump profile:
- Set
CoyoteTime = 0.15seconds after leaving ground, or0to disable.
Add Jump Buffer
On the assigned jump profile:
- Set
JumpBufferTime = 0.2seconds before landing, or0to disable.
Adding Movement Speed Buffs/Debuffs
Create Speed Modifier Effect
- Create new GameplayEffect Blueprint
- Configure:
- Duration: Duration or Infinite
- Modifier: Attribute = WalkSpeed, Op = Additive or Multiplicative
- Magnitude: Set By Caller using
SetByCaller.Magnitude.WalkSpeed
Apply from Blueprint
text
Get Ability System Component
├── Make Outgoing Spec (YourSpeedEffect, Level 1)
├── Assign Set By Caller Magnitude (SetByCaller.Magnitude.WalkSpeed, SpeedBonus)
└── Apply Gameplay Effect Spec to Self → Store Handle (for later removal)Apply from C++
cpp
// Apply speed buff
void ApplySpeedBuff(float SpeedBonus, float Duration)
{
if (UAbilitySystemComponent* ASC = UMotionAbilitySystemHelper::GetAbilitySystemComponentFromActor(Character))
{
FGameplayEffectContextHandle Context = ASC->MakeEffectContext();
FGameplayEffectSpecHandle Spec = ASC->MakeOutgoingSpec(SpeedBuffEffect, 1.0f, Context);
if (!Spec.IsValid())
{
return;
}
Spec.Data->SetSetByCallerMagnitude(
MotionGameplayTags::SetByCaller_Magnitude_WalkSpeed,
SpeedBonus
);
if (Duration > 0.0f)
{
Spec.Data->SetDuration(Duration, true);
}
SpeedBuffHandle = ASC->ApplyGameplayEffectSpecToSelf(*Spec.Data.Get());
}
}The C++ example overrides the effect spec's duration only when Duration is positive; pass 0 to keep the GameplayEffect asset's configured duration.
Remove the stored SpeedBuffHandle later with RemoveActiveGameplayEffect after checking that the handle is valid.
Creating Custom Movement States
Add a New State Tag
Define your tag in your project's GameplayTags:
Motion.State.Sliding Motion.State.WallRunning Motion.State.SwimmingCreate an Infinite GameplayEffect, add a Target Tags Gameplay Effect Component, and add your state tag to its granted tags.
React to Custom State
In Animation Blueprint
Add to GameplayTagPropertyMap:
Tag: Motion.State.Sliding
Property: bIsSliding (Bool)In Other Components
cpp
bool bIsSliding = UMotionAbilitySystemHelper::ActorHasGameplayTag(
Character,
FGameplayTag::RequestGameplayTag(FName(TEXT("Motion.State.Sliding")))
);Block Other States
GameplayEffect application requirements do not automatically prevent Motion's built-in components from entering their states. Add a check for your custom tag in C++ overrides such as CanStartSprinting() or CanPerformJump(), and add an equivalent gate to any crouch or custom input path that should be blocked.
Integrating with Ability Cooldowns
Register the cooldown tags used by your project, then create Duration GameplayEffects that grant those tags through a Target Tags Gameplay Effect Component.
Sprint with Cooldown
Override CanStartSprinting() in a C++ child class (Blueprint override not supported):
cpp
// In your C++ child class
class UMySprintComponent : public UMotionSprintingComponent
{
protected:
virtual bool CanStartSprinting() const override
{
if (UAbilitySystemComponent* ASC = CachedAbilitySystemComponent)
{
if (ASC->HasMatchingGameplayTag(FGameplayTag::RequestGameplayTag(FName(TEXT("Ability.Cooldown.Sprint")))))
{
return false;
}
}
return Super::CanStartSprinting();
}
};Jump with Cooldown
Override CanPerformJump() in a C++ child class (Blueprint override not supported):
cpp
// In your C++ child class
class UMyJumpComponent : public UMotionJumpComponent
{
protected:
virtual bool CanPerformJump() const override
{
if (UAbilitySystemComponent* ASC = CachedAbilitySystemComponent)
{
if (ASC->HasMatchingGameplayTag(FGameplayTag::RequestGameplayTag(FName(TEXT("Ability.Cooldown.Jump")))))
{
return false;
}
}
return Super::CanPerformJump();
}
};Blueprint child classes cannot override these checks. For a Blueprint-only project, gate the input execution before calling the Motion component, or expose a project-specific C++ function that performs the tag check.
Apply Cooldown After Action
cpp
void ApplyCooldown(TSubclassOf<UGameplayEffect> CooldownEffect)
{
if (UAbilitySystemComponent* ASC = CachedAbilitySystemComponent)
{
FGameplayEffectContextHandle Context = ASC->MakeEffectContext();
FGameplayEffectSpecHandle Spec = ASC->MakeOutgoingSpec(CooldownEffect, 1.0f, Context);
if (Spec.IsValid())
{
ASC->ApplyGameplayEffectSpecToSelf(*Spec.Data.Get());
}
}
}Adjusting Crouch Speed
Change Speed Modifier
On the assigned crouch profile:
CrouchWalkSpeedModifier = -200.0 (negative to slow down)Variable Crouch Speed
Create a custom GameplayEffect with SetByCaller magnitude:
cpp
// Apply variable crouch speed
FGameplayEffectContextHandle Context = ASC->MakeEffectContext();
FGameplayEffectSpecHandle Spec = ASC->MakeOutgoingSpec(CrouchSpeedEffect, 1.0f, Context);
if (Spec.IsValid())
{
Spec.Data->SetSetByCallerMagnitude(
MotionGameplayTags::SetByCaller_Magnitude_CrouchSpeed,
CalculatedSpeedModifier
);
ASC->ApplyGameplayEffectSpecToSelf(*Spec.Data.Get());
}Adding Camera Effects to Movement
Sprint Camera Shake
On the assigned sprint profile:
- Set
bApplyCameraShake = true. - Configure the
SprintCameraShakecurve.
Landing Camera Impact
The MotionJumpComponent already broadcasts landing events. Subscribe in Blueprint:
text
Event OnLandedDelegate
├── Get Character Movement Component
├── Get Last Update Velocity → Calculate Impact from Z velocity
├── Create Landing Camera Curve
└── Add Motion Curve on MotionCameraComponentExtending Component Behavior
Blueprint Child Class
- Create a Blueprint child of a Motion component.
- Bind its Blueprint-assignable delegates, such as
OnSprintStateChangedDelegate, to react to state changes.
Virtual functions such as CanStartSprinting() and the protected UpdateSprintingState(float DeltaTime) require a C++ child class; they are not Blueprint override events.
C++ Child Class
cpp
UCLASS()
class UMySprintComponent : public UMotionSprintingComponent
{
GENERATED_BODY()
protected:
virtual void BeginPlay() override
{
Super::BeginPlay();
OnSprintStateChangedDelegate.AddDynamic(this, &UMySprintComponent::HandleSprintStateChanged);
}
virtual bool CanStartSprinting() const override
{
// Add custom logic
if (!Super::CanStartSprinting())
return false;
// Your project-specific condition.
return bCanSprintBasedOnEquipment;
}
UFUNCTION()
void HandleSprintStateChanged(bool bIsSprinting)
{
// Your custom handling
if (bIsSprinting)
{
// Trigger project-specific sprint feedback.
}
}
UPROPERTY(EditAnywhere, Category = "Sprint")
bool bCanSprintBasedOnEquipment = true;
};Next steps
Use the reference pages when a customization needs exact API or Gameplay Ability System details.