LoginSignup
7
4

【UE5】GameplayAbilitySystem実践編【GAS】

Last updated at Posted at 2023-12-12

この記事はUnreal Engine (UE) Advent Calendar 2023の13日目の記事です。

概要

前回からの続きです。

前回の記事で入門したので実際に使う場合を想定してコンボ攻撃や
スタミナ消費攻撃などを実装していきます。

単発の攻撃を実装する

まずは攻撃用のアニメーションとMontageを用意します。
image.png

Ability内でMontageの再生を行う

新しく「GA_Attack」というAbilityを作成し、[PlayMontageAndWait]ノードでMontageを再生します。
また、前回は端折りましたが、ActivateAbilityの後に[CommitAbility]ノードを追加します。
[CommitAbility]ノードと[EndAbility]ノードはセットのようなものなので基本的には呼び出してください。
image.png

これを実行することでアニメーションが再生されることが確認できると思います。

このままの場合、連打すると攻撃を振り終わる前に次の攻撃を振ったりして良くないので
AbilityTagによって自分の攻撃中は同じ攻撃が出せない様にします。
image.png
前回のものから引き続き実装している場合、起動用の[AbilityTag]が変わっているためこちらも合わせるようにしましょう
image.png

攻撃判定を発生させる通知を作る

攻撃判定を発生させるにあたり、Montageの任意のタイミングをAbilityに通知する必要があります。
まずはAbility内に通知を受け取るための[WaitGameplayEvent]ノードをMontageと同じタイミングで実行します。
このノードはどこかからEventTagに設定されているタグを指定して対となる[SendGameplayEventtoActor]が呼び出された場合に、EventReceivedが起動するというものになります。
image.png

ではMontage内で通知を送るためにAnimNotifyクラスのBPを作成し(名前はAN_SpawnDamageとしています)
ReceiveNotify関数をオーバーライドし、こんな感じに組みます。
image.png
Payloadという引数には自由な情報を書き込むことができ、
特にOptionalObjectの2枠はObject型…
つまりほとんどのクラスを引数として渡せるワイルドカードとして扱うことができるため、
もしアニメーションで設定した数値をAbility側で反映させたいといった事があればここを利用するといいでしょう。

AnimNotifyができたらMontageに設定して…
image.png

Ability側で通知を受け取った後の挙動を追記すれば…
image.png

攻撃モーションを行い、任意のタイミングで処理が実行されることが確認できると思います。
攻撃判定は各自お好みで実装してください。
image.png

コスト消費攻撃を実装する

ひとまず攻撃を実行できるようになったので、スタミナを消費して攻撃するようにしてみます。
今回はスタミナが足りない場合は攻撃が行えない。という仕様とします。

まずは[ThirdPeasonCharacter]にスタミナ用の変数を作成しておきます。
(デフォルト値を100としています)
image.png
キャラクター側の処理はこれだけ。

Abilityにコストの設定を行う

次はAbility[GA_Attack]にコスト用の変数を準備します。
(今回はコストのデフォルト値を15としています)
image.png

それが済んだらAbilityの関数[CanActiveteAbility]をオーバーライドします。
image.png

この関数は戻り値のBool型[ReturnValue]がTrueの場合のみAbilityの起動を許可するフラグのような関数です。
image.png
その関数を以下のように
「スタミナが足りていれば攻撃を実行。足りなければ攻撃は失敗とする」
そういった処理を実装します。
image.png

同じように[CommitExecute]関数もオーバーライドし、スタミナを消費する処理を実装します。
この関数は[CommitAbility]ノードを呼び出した際に実行されます。
image.png

結果

攻撃を実行時にコストとして設定した値が消費されました。
また、何度も攻撃することでいずれコスト不足になり、攻撃が行えなくなります。
image.png

コンボ攻撃を実装する

ここまでで単発の攻撃の実装ができたので、コンボ攻撃の作り方の紹介をします。

大まかな内容はこんな感じで、Montageに[AnimNotifyState]を追加して
コンボ攻撃1を実行中にコンボ攻撃2の準備をしておき、コンボ攻撃1を終了していいタイミングでコンボ攻撃2のMontage等の処理を実行します。
image.png

コンボ攻撃2を作成する

まずは最初に作ったMontageに2つ目のコンボを追加します。
image.png

新たにAbilityの[GA_Attack2]を作成し2つ目の攻撃アニメーションが再生されるようにします。
この時[WaitGameplayEvent]ノードを挟むことで、コンボ攻撃1が許可するまでコンボ攻撃2が実行されないようにします
image.png

また、後述する理由でAbilityTagの設定は以下のようにしておきます。
コンボ攻撃1と同じタグで起動し、自身のAbility中は同じAbilityを実行せず
[Action.State.ComboReady]タグを所有している場合に起動可能という設定となります。
image.png
もちろんAbilityを作成した後はプレイヤー側への追加は忘れないようにします。
image.png

ここでコンボ攻撃1に戻りますが、コンボ攻撃2を実行中に1が起動しては困るため
[ActivationBlockedTags]に[Action.Test.Attack2]を追加します。
image.png

コンボ連携用のAnimNotifyStateを作成する

次に[AnimNotifyState]を作成します。
今回必要になる[AnimNotifyState]は2つで

  • ボタン入力を受け付けて、入力された場合にコンボ攻撃2を待機状態にするもの
  • コンボ攻撃2が待機状態の場合にコンボ攻撃2を実行するもの

コンボ受付用のAnimNotifyStateを作成する

[AnimNotifyState]の開始~終了までの間、指定したタグを付与するという動作を実装します。
これにより、この区間でのコンボ攻撃2の発動条件を満たします。

まずは[AnimNotifyState]を作成します。(名前は[ANS_AttackReady]とします)
変数として[GameplayTag型]の変数を[スポーン時に公開]にチェックを入れて追加します。
image.png

[Receive_NotifyBegin]関数及び[Receive_NotifyEnd]関数をオーバーライドし、
それぞれ以下のように組みます
image.png
image.png
古い情報源だと[AddGameplayTag]や[RemoveGameplayTag]を使うと書かれているものもありますが
現在はこちらのノードが正しいため要注意です。

待機状態のコンボ攻撃2を実行するAnimNotifyStateを作成する

先ほどと同じく[AnimNotifyState]を作成し、(名前は[ANS_AttackBrunch]とします)
[ReceivedNotifyTick]をオーバーライドし以下のように組みます。
image.png
そのステート期間中は毎フレームこのタグで止めているAbilityを進行させます。

Montageに設定する

上記2つの[AnimNotifyState]をMontageに設定していきます。
大体このような感じで配置しますが、[ANS_AttackReady]の終端が[ANS_AttackBrunch]の終端より手前で終わる様にしましょう。
image.png
また、[ANS_AttackReady]をクリックして出てくる詳細で[BeginAbilityTag]に[Action.State.ComboReady]を設定します。
image.png

ここまでの実装により、コンボ攻撃1を実行中に
[Action.State.ComboReady]というタグが一定時間付与されて
このタグが付与されている場合にのみ実行可能なコンボ攻撃2が起動し
[ANS_AttackBrunch]の[SendGameplayEventtoActor]により起動済みのコンボ攻撃2が進みアニメーションが再生される様になります。
Videotogif.gif

まとめ

色々と準備するものが多く長くなりましたが
ここまで実装してきてプレイヤー側への追記はコンボ攻撃2のGiveAbilityのみであり、
攻撃実行の処理はコンボ攻撃1と2で共有している状態となります。
似たような形でコンボ攻撃3以降も作れるため煩雑なフラグ管理を減らせるのが強みとなります。
GamePlayAbilitySystemで巨大なSwitchや変数管理とはオサラバしましょう

小ネタ

[GiveAbility]時の戻り値である[AbilitySpecHandle]から[GetGameplayAbilityfromSpechandle]ノードを使うことで
Abilityの実体を取得できるので、何らかの理由でフィードバックが要る場合などに使えると思います。
image.png

基本的にエディタ上でタグの削除はできません。
間違えて追加してしまったり、不要になったタグを消したい場合は
Config/DefaultGameplayTags.ini
の中にタグリストがあるためここから削除することで無かったことにできます。

※当然ですが使用中のタグだった場合動作しなくなるなどの不具合が起こるため重々注意してください。

タグの削除について追記

Project設定の中のGameplayTags項目にある
GameplayTagList内の矢印から削除ができる事を教えてもらいました。
image.png

ただし、ここで削除できるのは「どこにも使われていない状態のタグ」だけなので、
参照を検索から使われている箇所を逐一消していく必要はあります。
image.png

間違えて作ったタグぐらいであれば未使用でしょうし、こちらで消したほうが手間はなさそうで良いですね。

7
4
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
7
4