Appearance
How to customize Motion movement behavior
This guide gives practical examples of common changes to the Motion movement system.
Component profile assets contain behavior defaults. To adjust a project, duplicate the assigned Motion profile in project content. Edit the duplicate and assign it to the component Profile property. See Component profiles for the profile procedure.
Use the section that matches the applicable behavior. Each procedure is independent.
Add stamina drain to sprint
The Motion sprint component includes stamina support. Use this procedure to enable and adjust it.
Enable the stamina system
- Duplicate the assigned sprint profile.
- Set
bUseStaminaSystem = true. - Configure stamina thresholds:
| Property | Description | Supplied default |
|---|---|---|
MinStaminaToSprint | Minimum stamina 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_SprintStaminaRegenDelaySet a custom drain rate
Create a custom GameplayEffect Blueprint:
- Duplicate
GE_Motion_SprintStaminaDrain - Modify the periodic effect magnitude
- Assign your custom effect to the sprint profile
React to exhaustion in Blueprint
text
Event OnSprintStaminaDepletedDelegate
├── Play Sound (Exhaustion_SFX)
├── Play Camera Shake (Exhaustion_Shake)
└── Show UI WarningModify jump behavior
Add multiple jumps
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 during a jump. It calculates CharacterMovementComponent->JumpZVelocity from the initial stored value and profile modifiers. Thus, use 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.
Add movement speed effects
Create Speed Modifier Effect
- Create new GameplayEffect Blueprint
- Configure:
- Duration: Duration or Infinite
- Modifier: Attribute = WalkSpeed, Op = Additive or Multiplicative
- Magnitude: Set By Caller with
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 replaces the effect duration only when Duration is positive. Pass 0 to keep the configured GameplayEffect duration.
Make sure that the handle is valid. Then, remove the stored SpeedBuffHandle with RemoveActiveGameplayEffect.
Create custom movement states
Add a New State Tag
Define the tag in the project 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 requirements do not automatically stop built-in Motion component states. Evaluate the custom tag in C++ overrides such as CanStartSprinting() or CanPerformJump(). Add an equivalent condition to applicable crouch or custom input paths.
Integrate 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 functions. For a Blueprint-only project, add the condition before you call the Motion component. Alternatively, expose a project C++ function that evaluates the tag.
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());
}
}
}Adjust 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());
}Add 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 MotionCameraComponentExtend 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() must have a C++ child class. The protected UpdateSprintingState(float DeltaTime) must also have one. These functions 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 for exact API or Gameplay Ability System details.