関連ブログ
- [UE4][UE5]開発環境の容量を少しでも減らす 2024.08.14UE
- [UE5] PushModel型のReplicationを使い、ネットワーク最適化を図る 2024.05.29UE
- [UE5]マテリアルでメッシュをスケールする方法 2024.01.17UE
CATEGORY
2020.06.03UE4UE/ C++
執筆バージョン: Unreal Engine 4.24 |
ハローアンリアル!エンジニアの片平です。 今回はBPで組むと複雑になりがちなアクションゲームのコンボ攻撃の処理を、GameplayAbilitySystemのAbilityTag機能を使って作成してみました。
RPGやMOBA等で頻繁に使用されるアビリティを管理するシステムです。 アビリティとは、キャラクターが繰り出す攻撃、スキル、アイテム使用などのひとつひとつの「行為」です。 また、アビリティによって引き起こされるアトリビュート(=キャラクターの持つ数値、ステータス)の変化、発生するエフェクトなどの見た目上の挙動など関連する要素を効率的に実装することができます。 まだベータな機能ではありますが、FortniteやParagonなどの大型タイトルでも採用されているそうです。
今回は詳細や導入は省きます。上記の記事をご参照ください。 リファレンスプロジェクトとしてはActionRPGが非常に参考になります。 カバーする範囲が広い分、全体を把握しようと思うとかなり覚えることが多いですが、今回はGameplayAbilityComponent、GameplayAbilityのみを使用します。 GameplayEffect、GameplayAttribute、GameplayCue、GameplayTask、GameplayEventについては知らなくても構いません。 セットアップにはC++が必須となります。
GameplayAbilityに設定することができるTag(GameplayTag)です。
AbilityTagでAbilityの呼び出しや実行制限などの制御ができます。
つまり、Tagの設定だけでステート管理をすることができます。
今回使用する設定項目の効果について下記にまとめました。
AbilityTags | Ability自身が持っているTag |
Cancel Abilities with Tag | Abilityが実行されているときに、このTagをもつAbilityをキャンセルする |
Block abilities with Tag | Abilityが実行されているときに、このTagを持つAbilityを実行させない |
Activation Owned Tags | Abilityを実行している間、所有者にこのTagが付与される |
Activation Required Tags | 所有者がこのTagを持っているときのみ実行できる。 |
Activation Blocked Tags | 所有者がこのTagを持っているときは実行できない。 |
ThirdPersonテンプレートからC++プロジェクトを作成します。 今回はBlogComboというプロジェクト名で作成しました。
今回はマーケットプレイスのやたらかっこいいアニメーションアセットを使用しました。 Frank Action RPG Sword 1 (Basic Set) 以下のアニメーションを使用しています。
ThirdPersonのMannequinで使用できるように上記のアニメーションをリターゲットしておきます。 今回のアニメーションはrootに移動が入っているのでEnableRootMotionにチェックを入れておきました。
GameplayAbilitySystem はプラグインによって提供されています。 プラグイン設定からGameplay → GameplayAbilitiesのEnabledにチェックを入れて、指示通りエディタを再起動してください。
セットアップに関してはおかわり はくまい様の記事で非常に分かりやすくまとめられているため、そちらをご参照ください。 GameplayAbilityを拡張する都合上、(プロジェクト名).Build.csのPublicDependencyModuleNames.AddRangeには、GameplayAbilitiesの他、GameplayTags、GameplayTasksも追加しておいてください。
ThirdPersonテンプレートから作成していると、ThirdPersonCharacterの親となるCharacterクラス(ここではBlogComboCharacter)が出来ていると思うので、こちらにC++でGameplayAbilityComponentを追加します。
ビルドが終わると継承しているThirdPersonCharacterにもAbilitySystemComponentが追加されます。
デフォルトのGameplayAbilityではBP側から任意のタイミングでAbilityTagの追加/削除ができないためGameplayAbilityを継承したクラスで拡張します。 BlogComboGameplayAbility.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
#pragma once #include "CoreMinimal.h" #include "Abilities/GameplayAbility.h" #include "BlogComboGameplayAbility.generated.h" /** * */ UCLASS() class BLOGCOMBO_API UBlogComboGameplayAbility : public UGameplayAbility { GENERATED_BODY() /** AbilitySystemComponentのGameplayTagCountContainerに新しいGameplayTagを追加する */ UFUNCTION(BlueprintCallable, Category = "GamePlayAbility") virtual void AddGameplayTags(const FGameplayTagContainer GameplayTags); /** AbilitySystemComponentのGameplayTagCountContainerのGameplayTagを削除する */ UFUNCTION(BlueprintCallable, Category = "GamePlayAbility") virtual void RemoveGameplayTags(const FGameplayTagContainer GameplayTags); }; |
BlogComboGameplayAbility.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
#include "BlogComboGameplayAbility.h" #include "AbilitySystemComponent.h" void UBlogComboGameplayAbility::AddGameplayTags(const FGameplayTagContainer GameplayTags) { UAbilitySystemComponent* Comp = GetAbilitySystemComponentFromActorInfo(); Comp - > AddLooseGameplayTags(GameplayTags); } void UBlogComboGameplayAbility::RemoveGameplayTags(const FGameplayTagContainer GameplayTags) { UAbilitySystemComponent* Comp = GetAbilitySystemComponentFromActorInfo(); Comp - > RemoveLooseGameplayTags(GameplayTags); } |
これでBPからAbilityTagの追加/削除ができるようになりました。
コンボ1段目のAnimationMontageを作成します。
作成したAnimationMontangeに1段目のコンボで使用するアニメーションを追加します。
ThirdPerson_AnimBPを開き、AnimGraphを以下のようにつなぎ変えます。
これでDefaultSlotでAnimationMontageを再生することができるようになります。
先ほど作成したBlogComboGameplayAbilityを継承したBPを作成します。
作成したGameplayAbilityを開いて、以下のようにBPを組みます。
PlayMontageではMontage to Playに先ほど作成した1段目のAnimationMontageを指定します。 ClassDefaultsのTagsを以下のように設定します。
これによってAbility開始時にAbility.State.Combo1が所有者に付与され、Ability.Stateが付与されているときは実行できない、つまり二重に実行されるのを防ぐことができます。
ThirdPersonCaracterを編集していきます。 以下のようにClassDefaultsのAbilities – Ability Listに先ほど作成したGameplayAbilityを追加します。
以下のようなBPを組みます。
Zキーを押すとTryActiveAbilitiesbyTagノードでAbility.Action.Attackを指定して実行します。 これでAbilityList内でAbilityTagにAbility.Action.Attackを持つものが実行されます。 武器を持たせないと雰囲気が出ないため適当に持たせましょう。
以上の手順でZキーを押すと攻撃を繰り出すことができるようになります。
連打しても多重実行を禁止しているため、アニメーションが終わるまで再度実行はできません。
2段目のコンボを作成するには1段目のAnimationMontageにNotifyを設定する必要があります。 今回は先行入力も入れたいので、下の画像のようにアニメーション中に2種類の通知が必要となります。
1段目のAnimationMontageのNotifiesのトラックを右クリックし、Add Notify State → Montage Notify Windowを追加します。
これを上記の「A.入力可能」の通知として、始点を振り切るちょっと前くらい、終点を振り切ったちょっとあとくらいに設定しておきます。
DetailからNotifyNameを「Combo1.Input」としておきます。
さらに+ボタンでトラックを増やし、Montage Notify Windowを追加します。
これを上記の「B.次の攻撃に移行可能」の通知として、始点を振り切る瞬間、終点をAの終点と同時に設定します。
DetailからNotifyNameを「Combo1.Branch」としておきます。
1段目と同様にAnimationMontageを作成します。 2段目のアニメーションをセットします。3段目のためにNotifyも追加しておきましょう。
PlayMontageのOnNotifyBegin、OnNotifyEndから伸ばす形で以下のようなBPを追加します。
OnNotifyBeginが呼ばれた時にはNotify対応するタグを追加し、RemoveGameplayTagsが呼ばれた時にはNotifyに対応するタグを消してます。 <対応するタグ>
また、OnEndAbilityにもRemoveGameplayTagsを追加しましょう。
これでAbilityが終了したときに必ずAbility.Ready.Combo2、Ability.Begin.Combo2が消えるようになります。
2段目のGameplayAbilityを作成します。作成したBlogComboGameplayAbilityを継承します。
ClassDefaultsのTagsを以下のように設定します。
ActivationRequiredTagsにAbility.Ready.Combo2が入っているので、1段目のAnimationMontageで設定した「A.入力可能」の期間のみ実行することができます。 以下のようなBPを組みます。
WaitGameplayTagAddは指定したAbilityTagの追加があるまで待つノードです。
ここにAbility.Begin.Combo2を設定しているので、1段目のAnimationMonageで設定した「B.次の攻撃に移行可能」期間のみコンボアニメーションを再生できます。
ThirdPersonCaracterのClassDefaultsのAbilities – Ability Listに2段目のGameplayAbilityを追加します。
以上の手順で2段目のコンボができました。
連打すれば最速で2段目が出ます。ちょっと遅らせて入力すれば入力した瞬間2段目が出ます。
3段目以降も基本的に2段目と同様の作成の手順で作成できます。
というわけで今回はGameplayAbilitySystemのAbilityTagを使ってコンボ攻撃を作成してみました。 GamepalyAbilitySystemを使うことで非同期処理や効率的なネットワーク実装など様々なメリットが得られるのですが、今回はロジックを分散できる点が非常に嬉しいと実感できました。 CharacterのBPこれで済んじゃいますからね。
(参考)趣味で作ったプロジェクトのコンボ処理↓
GamepalyAbilitySystemは今回使ったもの以外にも便利な機能が盛りだくさんなので是非、活用してみてください!