Add animation Montage triggered through ability to play different Montage Sections.

This commit is contained in:
Caleb Buhungiro
2025-07-09 12:32:45 +08:00
parent 659e94c752
commit 0e12b3d0c3
10 changed files with 178 additions and 5 deletions

View File

@@ -1,4 +1,5 @@
;METADATA=(Diff=true, UseCommands=true)
[/Script/GameplayTags.GameplayTagsSettings]
ImportTagsFromConfig=True
WarnOnInvalidTags=True
@@ -11,4 +12,10 @@ InvalidTagCharacters="\"\',"
NumBitsForContainerSize=6
NetIndexFirstBitSegment=16
+GameplayTagList=(Tag="ability.basicattack",DevComment="Ability Tag assigned to basic attack abilities")
+GameplayTagList=(Tag="ability.combo.change",DevComment="")
+GameplayTagList=(Tag="ability.combo.change.combo01",DevComment="")
+GameplayTagList=(Tag="ability.combo.change.combo02",DevComment="")
+GameplayTagList=(Tag="ability.combo.change.combo03",DevComment="")
+GameplayTagList=(Tag="ability.combo.change.combo04",DevComment="")
+GameplayTagList=(Tag="ability.combo.change.end",DevComment="")

View File

@@ -0,0 +1,29 @@
// Multiplayer By Caleb
#include "Animations/AN_SendGameplayEvent.h"
#include "AbilitySystemBlueprintLibrary.h"
#include "GameplayTagsManager.h"
void UAN_SendGameplayEvent::Notify(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation,
const FAnimNotifyEventReference& EventReference)
{
Super::Notify(MeshComp, Animation, EventReference);
const auto OwnerActor{MeshComp->GetOwner()};
if (!OwnerActor) return;
if (const auto OwnerAsc{UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent(OwnerActor)}; !OwnerAsc) return;
UAbilitySystemBlueprintLibrary::SendGameplayEventToActor(OwnerActor, EventTag, FGameplayEventData());
}
FString UAN_SendGameplayEvent::GetNotifyName_Implementation() const
{
if (EventTag.IsValid())
{
TArray<FName> TagNames;
UGameplayTagsManager::Get().SplitGameplayTagFName(EventTag, TagNames);
return TagNames.Last().ToString();
}
return "None";
}

View File

@@ -2,3 +2,12 @@
#include "GAS/CGameplayAbility.h"
UAnimInstance* UCGameplayAbility::GetOwnerAnimInstance()
{
if (const auto OwnerSkeletalMeshComp{GetOwningComponentFromActorInfo()})
{
return OwnerSkeletalMeshComp->GetAnimInstance();
}
return nullptr;
}

View File

@@ -3,7 +3,10 @@
#include "GAS/GA_Combo.h"
#include "GameplayTagsManager.h"
#include "Abilities/Tasks/AbilityTask_PlayMontageAndWait.h"
#include "Abilities/Tasks/AbilityTask_WaitGameplayEvent.h"
#include "Abilities/Tasks/AbilityTask_WaitInputPress.h"
#include "GAS/UCAbilitySystemStatics.h"
UGA_Combo::UGA_Combo()
@@ -27,12 +30,90 @@ void UGA_Combo::ActivateAbility(const FGameplayAbilitySpecHandle Handle,
if (HasAuthorityOrPredictionKey(ActorInfo, &ActivationInfo))
{
const auto PlayComboMontage{
UAbilityTask_PlayMontageAndWait::CreatePlayMontageAndWaitProxy(this, NAME_None, ComboMontage)
UAbilityTask_PlayMontageAndWait::CreatePlayMontageAndWaitProxy(
this,
NAME_None,
ComboMontage
)
};
PlayComboMontage->OnBlendOut.AddDynamic(this, &UGA_Combo::K2_EndAbility);
PlayComboMontage->OnCancelled.AddDynamic(this, &UGA_Combo::K2_EndAbility);
PlayComboMontage->OnCompleted.AddDynamic(this, &UGA_Combo::K2_EndAbility);
PlayComboMontage->OnInterrupted.AddDynamic(this, &UGA_Combo::K2_EndAbility);
PlayComboMontage->ReadyForActivation();
/**
* Handle Setting the next combo section in current Montage
* This {ChangedEventTag} will mach all the tags under [changed] tag hierchy
* this will insure the event is Sents for all the tags(all the animation sections in Montage)
****/
const auto ChangedEventTag{GetComboChangedEventTag()};
const auto WaitComboChangeEventTask{
UAbilityTask_WaitGameplayEvent::WaitGameplayEvent(
this,
ChangedEventTag,
nullptr,
false,
false
)
};
WaitComboChangeEventTask->EventReceived.AddDynamic(this, &UGA_Combo::ComboChangedEventReceived);
WaitComboChangeEventTask->ReadyForActivation();
}
SetupWaitComboInputPressed();
}
void UGA_Combo::ComboChangedEventReceived(FGameplayEventData Data)
{
const auto EventTag{Data.EventTag};
if (EventTag == GetComboChangedEventEndTag())
{
NextComboName = NAME_None;
UE_LOG(LogTemp, Warning, TEXT("next combo is cleared"));
return;
}
TArray<FName> TagNames;
UGameplayTagsManager::Get().SplitGameplayTagFName(EventTag, TagNames);
NextComboName = TagNames.Last();
UE_LOG(LogTemp, Warning, TEXT("next combo is: %s"), *NextComboName.ToString());
}
FGameplayTag UGA_Combo::GetComboChangedEventTag()
{
return FGameplayTag::RequestGameplayTag("ability.combo.change");
}
FGameplayTag UGA_Combo::GetComboChangedEventEndTag()
{
return FGameplayTag::RequestGameplayTag("ability.combo.change.end");
}
void UGA_Combo::SetupWaitComboInputPressed()
{
const auto WaitInputPress{UAbilityTask_WaitInputPress::WaitInputPress(this)};
WaitInputPress->OnPress.AddDynamic(this, &UGA_Combo::HandleInputPress);
WaitInputPress->ReadyForActivation();
}
void UGA_Combo::HandleInputPress(float TimeWaited)
{
SetupWaitComboInputPressed();
TryCommitCombo();
}
void UGA_Combo::TryCommitCombo()
{
const auto OwnerAnimInstance{GetOwnerAnimInstance()};
if (NextComboName == NAME_None || !OwnerAnimInstance) return;
const auto SectionNameToChange{OwnerAnimInstance->Montage_GetCurrentSection(ComboMontage)};
OwnerAnimInstance->Montage_SetNextSection(
SectionNameToChange,
NextComboName,
ComboMontage
);
}

View File

@@ -0,0 +1,25 @@
// Multiplayer By Caleb
#pragma once
#include "CoreMinimal.h"
#include "GameplayTagContainer.h"
#include "Animation/AnimNotifies/AnimNotify.h"
#include "AN_SendGameplayEvent.generated.h"
/**
*
*/
UCLASS()
class CRUNCH_API UAN_SendGameplayEvent : public UAnimNotify
{
GENERATED_BODY()
public:
virtual void Notify(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation, const FAnimNotifyEventReference& EventReference) override;
private:
UPROPERTY(EditAnywhere, Category= "Gameplay Ability")
FGameplayTag EventTag;
virtual FString GetNotifyName_Implementation() const override;
};

View File

@@ -13,4 +13,6 @@ UCLASS()
class CRUNCH_API UCGameplayAbility : public UGameplayAbility
{
GENERATED_BODY()
protected:
UAnimInstance* GetOwnerAnimInstance();
};

View File

@@ -13,10 +13,27 @@ UCLASS()
class CRUNCH_API UGA_Combo : public UCGameplayAbility
{
GENERATED_BODY()
public:
UGA_Combo();
virtual void ActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, const FGameplayEventData* TriggerEventData) override;
virtual void ActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo,
const FGameplayAbilityActivationInfo ActivationInfo,
const FGameplayEventData* TriggerEventData) override;
static FGameplayTag GetComboChangedEventTag();
static FGameplayTag GetComboChangedEventEndTag();
private:
UFUNCTION()
void HandleInputPress(float TimeWaited);
void SetupWaitComboInputPressed();
void TryCommitCombo();
UPROPERTY(EditDefaultsOnly, Category="Amination")
TObjectPtr<UAnimMontage> ComboMontage;
UFUNCTION()
void ComboChangedEventReceived(FGameplayEventData Data);
FName NextComboName;
};