使いこなせたらすごく便利なGameplayAbilitySystemを解説していきます。
初回はGameplayAbilitySystemを使ってグレイマンをジャンプさせてみます。
え?グレイマンって最初からジャンプできるって!?・・・ま、まずはグレイマンからジャンプ能力を取り除く所から始めないといけないですね・・・
GameplayAbilitySystem概要
GameplayAbilitySystemは、以下の機能をまとめたフレームワークとなっています。
- GameplayAbility
- GameplayAttribute
- GameplayEffect
- GameplayTask
- GameplayEvent
- GameplayCue
- (GameplayTag) ← GAS以外でも利用することが多いのでカッコ書き
- (AbilitySystemComponent) ← GASを管理するコンポーネント
以下の図は、上記の機能の関連性をまとめたものとなっています。現時点ではこれを全て理解する必要はありません。今回のサンプルプログラムは、この中の一部分だけを使ってグレイマンをジャンプさせてみます。
上の図を見てみると、青いActorの枠の中にAbilitySystemComponentがあり、そこに緑のGameplayAbilityを登録していることが分かります。登録したGameplayAbilityを左上の赤い線で記述されたTryActivateAbilityTagという命令で発動させると、Actorの能力が実行されるという感じの構成になっていることが分かります。
今回のサンプルでは上の図の流れの中で一番最小限となる実装をしていきます。
プロジェクトの新規作成
初回なので、プロジェクトの生成から解説していきます。
プロジェクトの新規作成で「ゲーム」を選択してください。
サードパーソンを選択してください。
プロジェクト設定はデフォルトのままでOKです。プロジェクト名は適当に決めてください。(ここでは”GASSample”としました)
実家のような安心感のある画面が表示されました。
グレイマンの翼を剥ぐ
グレイマンからジャンプ機能を奪います。”/ThirdPersonBP/Blueprint/ThirdPersonCharacter”を開いてください。
Jump処理ノードを切り離し、グレイマンからジャンプ能力を奪います。(赤いバツ印の部分を切り離してください)
プレイボタンをクリックし、グレイマンがジャンプできなくなっていることを確認してください。確認できたらESCキーでプレイ画面から抜けます。
UnrealEngineのC++エディタの設定
GameplayAbilityはC++でしか登録できない為、C++を使える下準備を行います。(一度でも設定を行ったことがある場合は、この章の設定は不要です)
メニューの「編集」から「エディタの環境設定」を選択します。
エディタの環境設定ウインドウの左側のメニューの「一般」の中から「ソースコード」を選択し、ソースコードエディタに自分の環境にあったエディタを設定します。今回は愛用しているVisual Studio Code」を選択しました。
GameplayAbilitySystemプラグインの有効化
GASはプラグインで提供されているので、プラグインを有効化することで利用可能になります。歯車アイコンの「設定」から「プラグイン」を選択してください。
プラグインウインドウの検索枠に”Gameplay Abilities”と入力すると、検索結果に表示されるので、有効のチェックを入れてください。
するとエディタの再起動を求められるので、再起動してください。
C++関数ライブラリの作成
GameplayAbilityをActorのAbilitySystemコンポーネントへ登録するにはC++で登録する必要があります。今回は、C++側に最低限の処理を記述し、GameplayAbilityをActorのAbilitySystemコンポーネントへ登録できるようにします。
メニューの「ファイル」から「新規C++クラス」を選択してください。
親クラスを選択する画面では”Blueprint Function Library”を選択してください。
名前はなんでもいいので、デフォルトの”MyBlueprintFunctionLibrary”のままとしました。名前を確認したら「クラスを作成」ボタンをクリックしてください。
C++のコンパイルが実行されますので、終了までお待ちください。
コンパイルが終わると自動的にVisualStudioCode(以下、VSCode)が開くので、VSCodeのエクスプローラーから”「プロジェクト名」.Build.cs”というファイルを選択します。
追加は簡単で、赤丸の部分に”GameplayAbilities”を追加するだけです。
// Fill out your copyright notice in the Description page of Project Settings.
using UnrealBuildTool;
public class GASSample : ModuleRules
{
public GASSample(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "GameplayAbilities"});
PrivateDependencyModuleNames.AddRange(new string[] { });
// Uncomment if you are using Slate UI
// PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" });
// Uncomment if you are using online features
// PrivateDependencyModuleNames.Add("OnlineSubsystem");
// To include OnlineSubsystemSteam, add it to the plugins section in your uproject file with the Enabled attribute set to true
}
}
次にMyBlueprintFunctionLibrary.hを以下のように編集します。
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "AbilitySystemComponent.h"
#include "MyBlueprintFunctionLibrary.generated.h"
/**
*
*/
UCLASS()
class GASSAMPLE_API UMyBlueprintFunctionLibrary : public UBlueprintFunctionLibrary
{
GENERATED_BODY()
UFUNCTION(BlueprintCallable, meta = (DefaultToSelf = "Target"))
static void AddAbilityToComponent(AActor* Target, UAbilitySystemComponent* AbilitySystem, TSubclassOf<class UGameplayAbility> Ability);
};
MyBlueprintFunctionLibrary.cppは以下のようにします。
// Fill out your copyright notice in the Description page of Project Settings.
#include "MyBlueprintFunctionLibrary.h"
void UMyBlueprintFunctionLibrary::AddAbilityToComponent(AActor* Target, UAbilitySystemComponent* AbilitySystem, TSubclassOf<class UGameplayAbility> Ability){
if (Target && AbilitySystem && Ability){
AbilitySystem->GiveAbility(FGameplayAbilitySpec(Ability.GetDefaultObject(), 1, 1));
}
}
C++のソースを入力し終えたら、エディタの「コンパイル」をクリックしてください。
C++のソースコードが間違っていなければ、コンパイルが正常に行われるはずです。
GameplayAbilityを継承したジャンプ能力ブループリントの作成
次に、能力(Ability)を記述します。能力を格納する為に適当なフォルダを作成します。(今回はBPというフォルダを作成しました)
作成したフォルダの中でブループリントクラスの新規作成を選択してください。
“GameplayAbility”を選択して「選択」ボタンをクリックしてください。
新しく追加されたブループリントに”GA_Jump”と名前を付けます。これが、実際に能力の処理を書く為のブループリントとなります。
早速、能力処理を書く為に、GA_Jumpをダブルクリックして、ブループリントエディタを開いてください。
ロジックは以下のように実装します。
ActivateAbilityが能力処理のエントリーポイントとなります。GetOwningActorFromActorInfoで能力が割り当てられたActor(今回の例で言えばグレイマン)を取得し、ThirdPersonCharacterにキャストします。元々はジャンプボタンイベントで呼ばれていたJumpノードをここで呼び出し、最後にEndAbilityノードを呼び出します。
発生する可能性はありませんが、ThirdPersonCharacterにキャストできなかった場合も能力処理を終わらせる必要がある為EndAbilityを呼び出すようにしてください。
GameplayTagsの設定
メインのエディタに戻り、「設定」から「プロジェクト」設定を選択してください。
左側のメニューの「GameplayTags」を選択してください。
「新しいゲームプレイタグを追加」を開き、名前の入力欄に”ability.jump”と入力して、「新しいタグを追加」ボタンをクリックしてください。
GameplayTagListにabilityという第一階層のタグが追加され、その中にjumpというタグが追加されました。
ここまで確認ができたら「プロジェクト設定」ウインドウを閉じてください。
再びGA_Jumpの編集を開始します。イベントグラフのノードが無い部分をクリックし、右側に表示されている詳細パパネルを確認してください。(表示されていない場合は、画面上部の「クラスのデフォルト」をクリックすれば表示されます)
タグの中にAbilityTagsという項目があるので、ここで「編集」をクリックし、先ほど作成したability配下のjumpを選択します。
すると、AbilityTagsの右側に”ability.jump”と表示されます。
AbilitySystemコンポーネントをグレイマンに付与
グレイマンのブループリント”/ThirdPersonBP/Blueprints/ThirdPersonCharacter”を開きます。
コンポーネントの追加から「AbilitySystem」コンポーネントを選択します。
すると、CharacterMovementコンポーネントの下にAbilitySystemコンポーネントが追加されます。
ジャンプ能力の付与と能力の発動
引き続き、グレイマンのイベントグラフでロジックを作成していきます。
BeginPlayタグを作成し、そこからC++の関数ライブラリに唯一作成したAddAbilityToComponentノードを呼び出します。TargetにはSelfをいれ、AbilitySystemには先ほど作成した AbilitySystemコンポーネントを引っ張ってきて渡します。最後に、Abilityに先ほど作成した”GA_Jump”を選択しておきます。
これはグレイマン(Self)のAbilitySystemコンポーネント(AbilitySystem)に対して、ジャンプする能力(GA_Jump)を追加しているという意味になります。
次に能力の発動処理を書きます。
先ほど、グレイマンからジャンプの能力を奪ったので、その部分に能力の発動処理を書けば良さそうですね。
インプットアクションのJumpからTryActivateAbilityByTagノードを呼び出します。これは、最初の図にあった通り、タグ経由で能力を呼び出す命令となります。ターゲットには能力を登録したAbilitySystemコンポーネントを渡します。Gameplay Tag Containerには、GA_JumpでGamplayTagに設定しておいたability.jumpを渡したいので、MakeLiteralGameplayTagContainerノードを作成し、そこにability.jumpを設定します。
これでプレイしてみてください。
無事にグレイマンがジャンプするようになっていればOKです。(なお、元々の仕組みではJumpEndノードもあったので、ボタンの押している時間でジャンプの滞空時間が変化していたのですが、今回はジャンプする能力を発動しているだけですので滞空時間に変化はありません)
ってことは、能力を与えずに能力を発動させたらどうなるでしょうか?
再びグレイマンのイベントグラフを開き、BeginPlayでGA_Jumpで能力を登録していたAddAnbilityToComponentノードを呼び出さないようにしてみましょう。
改めてプレイすると、グレイマンがジャンプできなくなっています。能力が与えられていないので、ボタンを押しても能力を発動できないことが分かります。
総括
これで一通りのGameplayAbilityの実装が完了しました。
グレイマンは元々ジャンプできるので、なんかすごく遠回りな実装に見えますが、このサンプルから読み取れるGASの利点は
- 能力を単独のBPとして作成できるので、分業が可能になる(例えば、パンチやキックの能力処理をグレイマンのイベントグラフにではなく、GameplayAbilityを継承したブループリント上にそれぞれ記述できる)
- 能力の発動と実際の能力がGameplayTagで紐づいているだけなので能力の切り替えが容易になる
- 能力の付け外しが容易になり、能力の有無により処理の切り替えの必要が無い
という感じでしょうか?実は、GameplayAbilityの利点はこれだけではありません。次回は、GameplayTagを使って能力の発動制御を行っていきたいと思います。
No responses yet