GameplayAbilitiesの使い方(アビリティ編)

GameplayAbilitiesの使い方(セットアップ編)の続きです。

今回は実際にアビリティを作成してブループリントちゃんにくっつけていきます。

アビリティの作成

ここではDance,Flipの2つのアビリティを作ります。

最初に、コンテンツブラウザのコンテンツ配下に、Abilitiesフォルダを作ってください。

f:id:nca03132:20180730234802p:plain

この中に新規ブループリントを作成してください。

f:id:nca03132:20180730235104p:plain

「親クラスを選択」ではすべてのクラスをクリックし、その中でGameplayAbilityを選びます。

f:id:nca03132:20180730235255p:plain

作られたブループリントはGA_Danceと名称を変えます。

GA_Danceをダブルクリックして編集します。最初はクラスのデフォルトしか表示されないと思うので

f:id:nca03132:20180731062350p:plain

この「フルブループリントエディタを開く」をクリックしてイベントグラフを表示させます。

まずはデバッグ用にPrintStringを仕込みましょう。

f:id:nca03132:20180731064619p:plain

 こんな感じで、ActivateAbilityされたらDanceStartと表示してCommitAbilityを呼びます。今回は設定していませんがこれにより裏でアビリティの使用に必要なMP消費やクールダウンロジックが実行されます。その後3秒まってアビリティ終了。終了時にはDanceEndと表示。

できたらコンパイル・保存して、いったんGA_Danceは閉じます。

次に、コンテンツブラウザでGA_Danceを複製してGA_Flipも作っておきます。

f:id:nca03132:20180730235457p:plain

中身はほぼ一緒。PrintStringだけDanceの部分をFlipに変えておきます。

f:id:nca03132:20180731065015p:plainできたらコンパイルして保存します。

これでGA_Dance、GA_Flipの2つのアビリティが作成されました。

アビリティの実行

ではブループリントちゃんに実際にアビリティを実行してもらいましょう。

BP_BPchanを開いて、クラスのデフォルトを押し、詳細のAbilitiesという項目の中にあるAbilityListの"+"を2回押して項目を2つ追加します。それぞれプルダウンから"GA_Dance"、"GA_Flip"を指定します。

f:id:nca03132:20180731065802p:plain

ここでリストアップされたアビリティはセットアップ編のC++で書いたコードによりAbilitySystemに登録されます。これでブループリントちゃんは、DanceとFlipのアビリティが実行できるようになりました。

では実際に呼び出すコードを書いてみます。今回はデバッグ用なのでキーボードイベントの"1"、"2"を使って、Dance、Flipを呼び出してみましょう。

ブループリントちゃんのイベントグラフでキーボード1,2を押されたら、TryActivateAbilityByClassにより、アビリティを実行させます。

f:id:nca03132:20180731070154p:plain

こんな感じですね。これで1を押すとGA_Dance,2を押すとGA_Flipが呼び出されます。

コンパイル&保存して、実際にプレイしてみましょう。

f:id:nca03132:20180731070524p:plain

1を押したら左上にこんな感じでDanceStartが出て、3秒後にDanceEndが表示されます。2も同様です。

GameplayTagによる排他制御

さて、現在はデバッグプリントしか表示していませんが、将来的には1を押したらちゃんとブループリントちゃんにはダンスしてもらい、2を押したら前転してもらう予定です。が、ここで問題なのですが、現在1を連打すると連続でDanceが何度も実行されてしまいます。

f:id:nca03132:20180731071138p:plain

このままアニメーションを実装すると1を押すたびにアニメーションが頭から再生されてしまいおかしな状態になります。これを防ぐためにアビリティにGameplayTagを設定します。

GA_Danceを開いてもらい、クラスのデフォルトをクリックして詳細パネルの中のTagsの部分に注目してください。

f:id:nca03132:20180731071917p:plain

Tagsの一番上にある"Ability Tags"は、このアビリティが実行中に設定されるタグとなります。

3番目にある"Block Abilities with Tag"は、このアビリティ実行中は、このタグが設定されているアビリティの実行がブロックされることを表します。

つまり、この両方に同じタグを設定しておけば、最初の実行時にAbilitySystemに実行中のタグが通知され、連打による2回目のアビリティ実行はブロックされます。

アビリティが終了したら"Ability Tags"で設定したタグは自動的に消えるので、もう一度アビリティが実行できるようになります。

では、実際にタグを設定してみましょう。Ability Tags横の"Edit"を押して"Add New Gameplay Tag"を選択します。"Name"の部分に"Ability.Action.Dance"というタグを書き込んで"Add New Tag"をクリックします。

f:id:nca03132:20180731072658p:plain

これで

f:id:nca03132:20180731072752p:plain

こんな感じでタグが追加されたと思います。

次に、"Block Abilities with Tag"も同様にタグを追加します。

一度追加されたタグは、下部に表示されるアビリティリストの中からツリー上に選べるようになるので、

f:id:nca03132:20180731072953p:plain

こんな感じで"Ability.Action.Dance"を設定します。

コンパイル・保存してプレイしてみてください。連打してもアビリティが終了するまでは再実行されないようになっているはずです。

そうなるとGA_Flipについても同様に"Ability.Action.Flip"を設定すれば再実行は抑制され・・・るのですが、一つ問題が残ります。

DanceとFlipは本来同時にできてはいけないはずなのですが、現状はタグが別なのでセパレートに実行できてしまいます。

もちろん、Blockのタグにお互いのTagを追加していけば両方抑制できるのですが、アビリティが増えていくたびに追記するのも面倒です。

そこで利用できるのがタグの階層構造です。Dance,Flipのブロックアビリティを"Ability.Action"で止めておくと、アビリティ実行中、"Ability.Action"で始まるすべてのタグが設定されているアビリティの実行を抑制してくれます。

最終的に

GA_Danceのタグは

f:id:nca03132:20180731074652p:plain

GA_Flipのタグは

f:id:nca03132:20180731074718p:plain

となり、これで相互排他が可能となります。

 なお、今回は使用していませんでしたが、Cancel Abilities with Tagでは、このアビリティが実行されたときにキャンセルされるタグ(そのタグを持ったアビリティも中断されます)が指定できます。またActivationRequireTagsではアビリティ実行時に必要となる前提条件タグが設定できます。これにより何かのアビリティを実行中のみ実行可能なアビリティなども作ることができます。

アニメーションモンタージュの作成

さて、アビリティ編の最後に実際にアニメーションを再生させてみましょう。

今回は、通常の移動時はアニメーションのステートマシンで再生、アビリティ使用時はモンタージュで再生という形にします。

まずはコンテンツブラウザでBluePrintChan->Animationの中にあるBPChan_AnimBPを開いてください。

f:id:nca03132:20180731083730p:plain

アニムグラフのステートマシンの後ろに

f:id:nca03132:20180731085300p:plain

こんな感じでステートマシンから線をひっぱってMontage->DefaultSlotを選択。

f:id:nca03132:20180731085406p:plain

上記のようにResultにつなぎこみ、コンパイル・保存して閉じます。

次に、DanceとFlipのモンタージュを作ります。

(フォルダ構成としては適切でないですが、サンプルなので簡単に)コンテンツのAbilitiesフォルダで右クリックしてアニメーション→アニメーションモンタージュを選択します。

f:id:nca03132:20180731085900p:plain

ケルトン選択ではBPChan_Skeltonを選んで

f:id:nca03132:20180731090051p:plain

できたアニメーションモンタージュはAM_Danceという名前にしておきます。

f:id:nca03132:20180731090211p:plain

AM_Danceを開いて、A_Hip_Hop_Dancingをモンタージュグループにドラッグ&ドロップします。

f:id:nca03132:20180731090406p:plain

出来たら保存して閉じます。

同様にAM_Flipも作っておいてください。モンタージュグループにはA_Anim_FrontFlipをドラッグ&ドロップします。

アビリティ実行でモンタージュを再生

次にAbilityのBPにモンタージュの再生を指定します。

GA_Danceを開いてイベントグラフを編集します。

デバッグ用に入れてあるPrintStringを削除。

WaitDelayの代わりにPlayMontageAndWaitノードを入れます。

Montage to Playに再生させるAM_Danceを指定して、OnComplete,OnBlendOut,OnInterrupted,OnCanceledをすべてEndAbilityにつなぎます。

f:id:nca03132:20180731091409p:plain

同様にしてGA_FlipでもAM_Flipを再生させます。

f:id:nca03132:20180731091615p:plain

これで準備完了です。プレイで最終確認をしてください。

1を押すとダンス、2を押すとフリップが実行されます。また、それぞれ実行終了するまでは他のアビリティは排他され実行されないはずです。

f:id:nca03132:20180731091855p:plain

総括すると・・・

ここまでの実装で、アビリティごとにブループリントが独立していているのをご理解いただけたかと思いますが、これは結構便利なことです。

アビリティを増やすごとにブループリントを独立して作成し、そこにやるべきことを書いて能力を持たせたいキャラクタに登録すればいいので拡張がかなり楽です。

また自前でステート管理をしなくてもアビリティごとのGameplayTag設定で、かなり細かく実行抑制(遷移の管理)が可能です。

次回は!

現状はアビリティでモーションを再生さえているだけなので、次回はアビリティによるパラメータ(HPや移動速度など)変更を行う方法(GameplayEffectといいます)について紹介したいと思います。