UE4 C++ GameplayTagが追加/削除されたときに処理をする方法

やあ

制作中のゲームで状態異常を実装しようと思ったときに、どうすればいいんだーってAbilitySystemComponentのソースを読んでたらタグが追加/削除されたときに処理ができるのを見つけたのでメモとして書いておきます。

やる

MyCharacter.h

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "AbilitySystemInterface.h"
#include "MyCharacter.generated.h"

class UAbilitySystemComponent;

UCLASS()
class MYPROJECT_API AMyCharacter
    : public ACharacter, public IAbilitySystemInterface
{
    GENERATED_BODY()
public:
    AMyCharacter();

protected:
    virtual void BeginPlay() override;
    
    UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Character|Ability")
        UAbilitySystemComponent* AbilitySystemComponent;

public:
    UAbilitySystemComponent* GetAbilitySystemComponent() const override;

    /* このタグが追加/削除されたときにイベントを受け取ります。 */
    UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Character|State")
        FGameplayTag StunTag;
    /* タグが追加/削除されたときに呼び出される関数。 */
    virtual void StunTagChanged(const FGameplayTag CallBackTag, int32 NewCount);
};

MyCharacter.cpp

#include "MyCharacter.h"

AMyCharacter::AMyCharacter()
{
    AbilitySystemComponent = CreateDefaultSubobject<UAbilitySystemComponent>(TEXT("Ability System Comp"));
}

void AMyCharacter::BeginPlay()
{
    Super::BeginPlay();
    if (AbilitySystemComponent) 
    {
        /* タグが追加/削除されたときに処理が走るようにバインドする */
        AbilitySystemComponent->RegisterGameplayTagEvent(StunTag, EGameplayTagEventType::NewOrRemoved).AddUObject(this, &AMyCharacter::StunTagChanged);
        /* すでに追加されているタグが追加/削除されたときに処理が走るようにバインドする */
        AbilitySystemComponent->RegisterGameplayTagEvent(StunTag, EGameplayTagEventType::AnyCountChange).AddUObject(this, &AMyCharacter::StunTagChanged);
    }
}

UAbilitySystemComponent* AMyCharacter::GetAbilitySystemComponent() const
{
    return AbilitySystemComponent;
}

void AMyCharacter::StunTagChanged(const FGameplayTag CallBackTag, int32 NewCount)
{
    UE_LOG(LogTemp, Log, TEXT("StunTagChanged %s %d"), *CallBackTag.GetTagName().ToString(), NewCount);

    if (NewCount > 0)
    {
        /* DoStun */
    }
    else
    {
        /* StopStun */
    }
}

おまけ。GameplayEffectが適用/削除されたときに処理をしたい場合。

/* Hoge.h */
/* GameplayEffectが適用されたときに呼び出される処理 */
void EffectAdded(
    UAbilitySystemComponent* Source, 
    const FGameplayEffectSpec& SpecApplied, 
    FActiveGameplayEffectHandle ActiveHandle
);

/* GameplayEffectが削除されたときに呼び出される処理 */
void EffectRemoved(
    const FActiveGameplayEffect& RemovedEffect
);
/* Hoge.cpp */

void AHoge::BeginPlay()
{
    AbilitySystemComponent->OnGameplayEffectAppliedDelegateToSelf.AddUObject(
        this, &AHoge::EffectAdded
    );
    AbilitySystemComponent->OnAnyGameplayEffectRemovedDelegate().AddUObject(
        this, &AHoge::EffectRemoved
    );
}

void AHoge::EffectAdded(
    UAbilitySystemComponent* Source,
    const FGameplayEffectSpec& EffectSpec,
    FActiveGameplayEffectHandle EffectHandle
)
{
    UE_LOG(LogTemp, Log, TEXT("EffectAdded"));
}

void AHoge::EffectRemoved(const FActiveGameplayEffect& RemovedEffect)
{
    UE_LOG(LogTemp, Log, TEXT("EffectRemoved"));
}