2
0

UE5 GameplayAbilitySystemのブロックタグについてのメモ

Last updated at Posted at 2023-12-07

概要

UnrealEngine5 の GameplayAbilitySystem(GAS) での BlockTagについてのメモ。

Block Abilities with Tagを使うと指定タグを持つアビリティの発動をブロックできますが、アビリティ動作途中までブロックしたいようなケースがあったのでメモ書きです。

更新履歴

日付 内容
2023/12/07 初版
2024/07/09 アビリティ失敗時のタグ情報について追記

参考

以下の記事を参考にいたしました、ありがとうございます。
UE5公式:ゲームプレイアビリティシステム
UE公式:UAbilitySystemComponent::BlockAbilitiesWithTags
【UE5】GASと対話する【備忘録】

関連する過去記事

UE4 GameplayAbility Pluginについてのメモ

環境

Windows10
Visual Studio 2022
UnrealEngine 5.2.1

関連ソース

"Engine\Plugins\Runtime\GameplayAbilities\Source\GameplayAbilities\Public\AbilitySystemComponent.h"
"Engine\Plugins\Runtime\GameplayAbilities\Source\GameplayAbilities\Private\AbilitySystemComponent_Abilities.cpp"

GASのブロックタグについて

Block Abilities with Tag の動作

アビリティクラスの設定の Block Abilities with Tag にタグを設定すると、その設定されたタグを持つアビリティの起動をブロックすることができます。

AbilityTag.png

上記の設定だと、Ability.Skill.Test1 を持つアビリティが動作している間は Ability.Skill.Test2 が発動しないようにブロックしています。

Activation Block Tags の動作

こちらも設定したタグを持つアビリティの起動をブロックします。

ActivateBlockTags.png

Block Abilities with Tag の違いは該当のタグを持つアビリティをブロックする以外にもアクターが持っている場合にブロックされるようです、あとは失敗時のコールバック時に失敗理由判定タグがないなど細かい違いがあるようです。

アビリティ失敗時コールバック
// アビリティ発動失敗時コールバック
void AMyCharacter::OnAbilityFailed(const UGameplayAbility* _Ability, const FGameplayTagContainer& _GameplayTags)
{
	//# アビリティ発動失敗時コールバックに原因のゲームタグを得るには
	//# DefaultGame.ini に以下の登録と、UAbilitySystemGlobals::Get().InitGlobalData(); が必要(アセットマネージャ初期化でやるのがおすすめ)
	//# 
	//# [/Script/GameplayAbilities.AbilitySystemGlobals]
	//# ActivateFailCostName="Ability.Fail.Cost"
	//# ActivateFailCooldownName="Ability.Fail.Cooldown"
	//# ActivateFailTagsBlockedName="Ability.Fail.Block"
	//# ActivateFailTagsMissingName="Ability.Fail.RequiredTags"

	if( _GameplayTags.HasTag( FGameplayTag::RequestGameplayTag(FName("Ability.Fail.Cooldown"))) ){
		// クールダウン中
	}
	if( _GameplayTags.HasTag( FGameplayTag::RequestGameplayTag(FName("Ability.Fail.Cost"))) ){
		// コスト不足
	}
	if( _GameplayTags.HasTag( FGameplayTag::RequestGameplayTag(FName("Ability.Fail.Block"))) ){
		// 他のアビリティにブロックされた
  		// `Block Abilities with Tag`タグでブロックされた場合
	}
	if( _GameplayTags.HasTag( FGameplayTag::RequestGameplayTag(FName("Ability.Fail.RequiredTags"))) ){
		// 発動に必要なタグがない
	}
}

アビリティ実行途中でブロックをやめる

上記ブロックタグを使うと該当アビリティ動作中は指定のアビリティをブロックすることができますが、途中までブロックして解除したいというようなケースもあり得ます。
このような場合、GASのプロパティで Block Abilities with Tag を設定した上で AbilitySystemComponentクラスの UnBlockAbilitiesWithTags で解除。もしくはブロックしたいタイミングで BlockAbilitiesWithTags でブロックということもできるようです。

内部的にはBlockedAbilityTags でカウントしているのでブロック/アンブロックの呼び出し回数に注意が必要です。GASのインスタンスポリシーがEGameplayAbilityInstancingPolicy::InstancedPerActor の場合、アビリティが終了しても呼び出しカウンタが継続するため不具合となることが考えられます。

AbilitySystemComponent.h
	/** 特定のアビリティタグのブロックまたはブロックのキャンセル */
	void BlockAbilitiesWithTags(const FGameplayTagContainer& Tags);
	void UnBlockAbilitiesWithTags(const FGameplayTagContainer& Tags);

protected:
	/** これらのタグが付いているアビリティは発動できません */
	FGameplayTagCountContainer BlockedAbilityTags;

BlockAbilitiesWithTags UnBlockAbilitiesWithTags は以下のように実装されています。カウント数を取得/設定するには BlockedAbilityTagsに対し、GetTagCount() SetTagCount() で可能です。

AbilitySystemComponent.cpp
void UAbilitySystemComponent::BlockAbilitiesWithTags(const FGameplayTagContainer& Tags)
{
	BlockedAbilityTags.UpdateTagCount(Tags, 1);
}

void UAbilitySystemComponent::UnBlockAbilitiesWithTags(const FGameplayTagContainer& Tags)
{
	BlockedAbilityTags.UpdateTagCount(Tags, -1);
}

適用例

モンタージュに任意のイベントタグを入れて Play Montage Wait for Event等で受け取って切り替える方法があります。

Play Montage Wait for Event はデフォルトのプラグインには付属していません。
https://github.com/tranek/GASDocumentation を参考にしました。

Montage.png

MontageEvent.png

アニメーション通知の処理は以下のような感じになるかと思います。

AnimNotify_EventTag.cpp
void UAnimNotify_EventTag::Notify(
	USkeletalMeshComponent* MeshComp,
	UAnimSequenceBase* Animation,
	const FAnimNotifyEventReference& EventReference
	)
{
	AActor*			_Actor = MeshComp->GetOwner();
	ACharacter*		_Chara = Cast<ACharacter>(_Actor);
	
	if(_Chara){
		// イベント呼び出し
		FGameplayEventData _Payload;
		UAbilitySystemBlueprintLibrary::SendGameplayEventToActor(_Actor, EventTag, _Payload);
	}

}

その他

CanActivateAbility()で実行ブロック時の失敗情報付与

UGameplayAbility::CanActivateAbility() で独自にアビリティを実行失敗にした場合、OptionalRelevantTags に失敗原因タグをつけることでコールバックメソッドで受け取ることができます。
以下サンプルコード。

MyAbility.cpp
bool UMyGameplayAbility::CanActivateAbility(
	const FGameplayAbilitySpecHandle Handle,
	const FGameplayAbilityActorInfo* ActorInfo,
	const FGameplayTagContainer* SourceTags,
	const FGameplayTagContainer* TargetTags,
	OUT FGameplayTagContainer* OptionalRelevantTags
	) const
{
	if (!Super::CanActivateAbility(Handle, ActorInfo, SourceTags, TargetTags, OptionalRelevantTags))
	{
		// 失敗コールバック用にタグ情報を付与する
		OptionalRelevantTags->AddTag(FGameplayTag::RequestGameplayTag(FName("Ability.Fail.Other")));
		
		return(false);
	}

	return(true);
}
AMyCharacter.cpp
// アビリティ発動失敗時コールバック
void AMyCharacter::OnAbilityFailed(const UGameplayAbility* _Ability, const FGameplayTagContainer& _GameplayTags)
{
	if( _GameplayTags.HasTag( FGameplayTag::RequestGameplayTag(FName("Ability.Fail.Other"))) ){
		// CanActivateAbility()でfalseが返ってきた
	}
	
}

まとめ

BlockAbilitiesWithTags UnBlockAbilitiesWithTags はC++のみになっているため、BPで制御するにはアビリティコンポーネントを継承して使わないとならないようです。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0