Slide Ability – Advanced Movement System (AMS) Plugin in Lyra UE5
Learn how the Slide Ability is implemented using the Advanced Movement System (AMS) plugin in Lyra (UE5).
Introduction
This tutorial explains how sliding is handled through Gameplay Abilities, with a clean separation between input handling, movement logic, and gameplay conditions like blocking.

Configuration Variables
Several key variables used to control sliding are exposed directly in the CharacterMovementComponent
. They allow you to fine-tune sliding behavior to match the desired gameplay style.

Gameplay Ability
To handle sliding in our system, we have a dedicated Gameplay Ability named ULyraGameplayAbility_Slide
, which is very simple and inherits from the ULyraGameplayAbility
class provided by the Lyra framework.
This ability contains two methods:
StartSliding
StopSliding
These methods are called when the ability is activated or ended, and they simply delegate the action to the ACharacter
, which already contains the StartSliding
and StopSliding
functions as part of its own movement logic.
/** * ULyraGameplayAbility_Slide * * Gameplay ability used for character sliding. */ UCLASS() class LYRAGAME_API ULyraGameplayAbility_Slide : public ULyraGameplayAbility { GENERATED_BODY() public: ULyraGameplayAbility_Slide(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get()); protected: virtual bool CanActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayTagContainer* SourceTags, const FGameplayTagContainer* TargetTags, FGameplayTagContainer* OptionalRelevantTags) const override; virtual void EndAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, bool bReplicateEndAbility, bool bWasCancelled) override; protected: /** Indicates that the player intends to slide */ UFUNCTION(BlueprintCallable, Category = "Lyra|Ability") void StartSlide(); /** Indicates that the player intends to stop sliding */ UFUNCTION(BlueprintCallable, Category = "Lyra|Ability") void StopSliding(); };
In the constructor of this ability, we simply call the parent class constructor. This constructor sets up the ability to allow immediate client-side activation. At the same time, a request is sent to the server, which then validates or cancels the activation based on the game’s rules.
ULyraGameplayAbility::ULyraGameplayAbility(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer) { ReplicationPolicy = EGameplayAbilityReplicationPolicy::ReplicateNo; InstancingPolicy = EGameplayAbilityInstancingPolicy::InstancedPerActor; NetExecutionPolicy = EGameplayAbilityNetExecutionPolicy::LocalPredicted; NetSecurityPolicy = EGameplayAbilityNetSecurityPolicy::ClientOrServer; ActivationPolicy = ELyraAbilityActivationPolicy::OnInputTriggered; ActivationGroup = ELyraAbilityActivationGroup::Independent; bLogCancelation = false; ActiveCameraMode = nullptr; }
Although the Gameplay Ability System (GAS) is meant to handle the activation and deactivation of abilities, it should be noted that the CharacterMovementComponent
can change the character's movement mode in certain situations, for example when the character falls off a cliff. In this case, the movement mode automatically switches to MOVE_Falling
, which physically stops the slide by adapting the physics to falling.
In my implementation, I assume that the CharacterMovementComponent
handles this physical movement mode change and the associated cleanup, while I override the OnSlideInterrupted
method to send a Gameplay Event to the Ability System. This allows the Ability to become aware of the interruption and properly terminate itself via GAS.
void ULyraCharacterMovementComponent::OnSlideInterrupted() { SendGameplayEventToSelf(LyraGameplayTags::GameplayEvent_SlideInterrupted); }
That's all for the C++ setup. Now let's move on to the Blueprint part.
In our case, we are using an ability Blueprint named GA_Hero_Slide
, which inherits from the ULyraGameplayAbility_Slide
class defined in C++. This ability calls the StartSliding
method when activated, and StopSliding
when the ability ends, through a call to EndAbility
.
This Ability Blueprint also listens to the GameplayEvent.Slide.Interrupted
event emitted by the CharacterMovementComponent
. When this event is received, the ability calls EndAbility
to properly terminate the ability through the GAS system.


Triggering Ability via Player Input
To bind an Ability to player inputs in Lyra, you need to follow two main steps:
Define the input in the Input Data Asset
In the InputData_Hero
Data Asset, I added a new entry to the AbilityInputActions
list.
This entry includes:
An
InputAction
, which corresponds to the specific input action.An
InputTag
, which serves as a semantic identifier to link this input to the corresponding Ability in the system.

Associate the Ability in the Ability Set Data Asset
Then, in the AbilitySet_ShooterHero
Data Asset, I added a new entry to the GrantedGameplayAbilities
list.
This entry contains:
The Ability we want to grant.
The level of this Ability.
The corresponding Input Tag, which links the input to the activation of the Ability.

Camera Offset on the Z Axis During Slide
To visually support the lowered posture of the character while sliding, the camera is also shifted on the Z axis.
This behavior follows the same logic used for crouching, using the SetTargetCrouchOffset
method inside UpdateForCrouchTarget
.
void ULyraCameraMode_ThirdPerson::UpdateForTarget(float DeltaTime) { if (const ALyraCharacter* TargetCharacter = Cast<ALyraCharacter>(GetTargetActor())) { if (TargetCharacter->IsCrouched()) { const ACharacter* TargetCharacterCDO = TargetCharacter->GetClass()->GetDefaultObject<ACharacter>(); const float CrouchedHeightAdjustment = TargetCharacterCDO->CrouchedEyeHeight - TargetCharacterCDO->BaseEyeHeight; SetTargetCrouchOffset(FVector(0.f, 0.f, CrouchedHeightAdjustment)); return; } UAMS_CharacterMovementComponent* CharacterMovement = Cast<UAMS_CharacterMovementComponent>(TargetCharacter->GetCharacterMovement()); if (CharacterMovement && CharacterMovement->IsSliding()) { const AAMS_Character* TargetCharacterCDO = TargetCharacter->GetClass()->GetDefaultObject<AAMS_Character>(); const float SlidedHeightAdjustment = TargetCharacterCDO->SlidedEyeHeight - TargetCharacterCDO->BaseEyeHeight; SetTargetCrouchOffset(FVector(0.f, 0.f, SlidedHeightAdjustment)); return; } } SetTargetCrouchOffset(FVector::ZeroVector); }
Horizontal Camera Offset During Slide
To move the camera horizontally during the acceleration caused by sliding, we reuse the SetTargetAccelerationOffset
method, which was originally implemented for sprinting.
We simply modify the offset value applied in the UpdateForAccelerationTarget
method by checking if the character is sliding via CharacterMovement->IsSliding()
:
void ULyraCameraMode_ThirdPerson::UpdateForAccelerationTarget(float DeltaTime) { if (const ALyraCharacter* TargetCharacter = Cast<ALyraCharacter>(GetTargetActor())) { if (UAMS_CharacterMovementComponent* CharacterMovement = Cast<UAMS_CharacterMovementComponent>(TargetCharacter->GetCharacterMovement())) { if (CharacterMovement->bIsSprinting) { SetTargetAccelerationOffset(100.f); return; } if (CharacterMovement->IsSliding()) { SetTargetAccelerationOffset(150.f); return; } } } SetTargetAccelerationOffset(0.f); }
In this example, an offset of 150.f
is applied during the slide, creating a more pronounced camera pull-back effect than sprinting.