
UGameplayAbility
クラスから派生した ゲームプレイ アビリティ はゲーム内のアビリティの実行内容や、 (もしあれば) 使用に際してのコストや、いつもしくはどんな状況で使用可能か、といった内容を定義します。ゲームプレイ アビリティは非同期に実行するインスタンス化されたオブジェクトとして存在可能なので、キャラクター アニメーション、パーティクル、サウンドエフェクトを使った多段階のタスクの実行、さらには、プレイヤーの入力や実行中に発生したキャラクターとのインタラクションによって処理を分岐することもできます。ゲームプレイ アビリティ自体がネットワークにまたがってレプリケートすることが可能で、クライアントまたはサーバー マシン上で実行すること (クライアントサイドでは予想もサポート)、さらには変数を同期してリモート プロシージャ コール ( RPC) を生成することが可能です。ゲームプレイ アビリティはまた、エンジンがそれらをゲーム セッション中どのように実装するかという点での柔軟性を提供します。たとえば、クールダウンと使用コスト、プレイヤー入力、 アニメーション モンタージュによるアニメーション、アクタにアビリティ自体が与えられた時の応答を実装する拡張機能などです。
アビリティの承認と取り消し
アクタがアビリティを使えるようにするには、Ability System コンポーネントがそのアビリティを承認しなければなりません。以下の Ability System Component 関数でアビリティへのアクセスを許可することができます。
-
GiveAbility
:アビリティがFGameplayAbilitySpec
で追加され、FGameplayAbilitySpecHandle
を返すように指定します。 -
GiveAbilityAndActivateOnce
:アビリティがFGameplayAbilitySpec
で追加され、FGameplayAbilitySpecHandle
を返すように指定します。アビリティはインスタンス化され、サーバー上で実行可能でなければなりません。サーバー上でアビリティの実行を試みた後、FGameplayAbilitySpecHandle
が返されます。アビリティが要件基準に満たない場合、または実行できない場合、戻り値は無効となり、Ability System Component はアビリティを許可しません。
以下の関数は、アビリティが許可されると返される FGameplayAbilitySpecHandle
を使って、Ability System Component からアビリティへのアクセスを取り消します。
-
ClearAbility
:特定のアビリティを Ability System Component から除去します。 -
SetRemoveAbilityOnEnd
:特定のアビリティを実行終了時に Ability System Component から除去します。アビリティが実行中でない場合、直ちに除去されます。アビリティが実行中の場合、入力は直ちにクリアされ、その後プレイヤーは反応やインタラクトが一切できなくなります。 -
ClearAllAbilities
:すべてのアビリティを Ability System Component から除去します。FGameplayAbilitySpecHandle
を要求しない唯一の関数です。
基本的な使い方
アクタのアビリティ システム コンポーネントへ許可された後の、ゲームプレイ アビリティの基本実行ライフサイクルは以下のようになります。
-
TryActivateAbility
関数がアビリティが即実行可能か決定するためにCanActivateAbility
を呼び出して可能なら実行します。CanActivateAbility
は、アビリティを表すアイコンをグレイアウトさせたり隠すために実際にアビリティの実行を行わずにアビリティを実行可能かゲームが知る必要がある場合に、単独で呼び出すことができます。 CallActivateAbility
はアビリティを実行する予定のゲームコードを実行し、TryActivateAbility
に呼び出されます。CanActivateAbility
チェックが不要であれば直接この関数を呼び出すことも可能です。-
ユーザーがアビリティのカスタム機能でオーバライドする必要のあるメイン コードは
ActivateAbility
という名前の C++ 関数か、Activate Ability という名のブループリント イベントです。 -
ゲームプレイ アビリティはアクタとコンポーネントが実行するような「ティック」関数で主要な仕事を実行しません。かわりに、アクティベーション中にほとんどの作業を非同期に実行するアビリティ タスクを起動して、これらタスクの出力を (C++ の) デリゲートにフックするか、ノードを (ブループリントの) 出力実行ピンに接続することで処理します。
-
CommitAbility
関数がアクティベート内で呼び出されると、たとえば、ゲームプレイ アトリビュート (「マジック ポイント」「スタミナ」その他ゲームで必要などんなものでも) からリソースを差し引くことで、そのアビリティを実行するコストを適用し、クールダウンを適用します。 -
CancelAbility
はアビリティをキャンセルする仕組みを提供しますが、CanBeCanceled
関数はその要求を拒否することができます。CommitAbility
と異なり、この関数はアビリティ自体の外の呼び出し元から利用できます。キャンセルが成功すると、アビリティを有効にする標準コードパスに行く前に On Gameplay Ability Cancelled にブロードキャストされます。アビリティは特別なクリーンナップ コードを実行したり、キャンセル時に通常終了と違う振舞いをすることができます。
-
-
TryActivateAbility
はアビリティを実行する典型的な方法です。TryActivateAbility
関数がアビリティが即実行可能か決定するためにCanActivateAbility
を呼び出して可能なら実行します。 - 正常終了のために、アビリティは、C++ 関数
EndAbility
か、ブループリントの End Ability ノードを呼び出す必要があります。アビリティがキャンセルされると、この関数がUGameplayAbility
コードによりキャンセル処理の一環として自動的に呼び出されますが、その他すべての場合において、デベロッパーは C++ 関数を呼び出すか、またはアビリティのブループリント グラフにノードを追加しなければなりません。アビリティの正常終了に失敗すると、ゲームプレイ アビリティ システムにより、アビリティがまだ実行中であるとみなされてしまい、以降、アビリティの使用が妨げられたりアビリティがブロックされるという影響が出ます。たとえば、ゲームに「ヘルス ポーションを飲む」という、正常終了していないゲームプレイ アビリティがある場合、他のポーションを飲んだり、スプリントしたり、はしごを登ったりといったような、ヘルス ポーションを飲んでいる最中にできないアクションは無制限にできなくなります。ゲームプレイ アビリティ システムはまだドリンクが飲み終えられていないと判断するからです。
Unreal Engine プロジェクトでの設定方法については、「アクション RPG のゲームプレイ アビリティ」 を参照してください。
タグ
Gameplay Tags は、ゲームプレイ アクティビティがどのようにインタラクションするかについて決定する時に有益です。各アビリティは、振る舞いに影響を与えられるように、アビリティを識別、カテゴライズするタグのセットや、他のアビリティによるこれらのインタラクションをサポートするゲームプレイ タグ コンテナとゲームプレイ タグ クエリを保持します。
ゲームプレイのタグ変数 | 目的 |
---|---|
Cancel Abilities With Tag | アビリティ実行中に提供されたリストにマッチするタグを持つ、すでに実行されているアビリティをすべてキャンセルします。 |
Block Abilities With Tag | アビリティ実行中に、タグにマッチする他のアビリティを実行させません。 |
Activation Owned Tags | アビリティ実行中に、アビリティのオーナーにこのタグのセットを与えます。 |
Activation Required Tags | アクティベートするアクタまたはコンポーネントがこれらすべてのタグを持っているときのみ、アビリティをアクティベートできます。 |
Activation Blocked Tags | アクティベートするアクタまたはコンポーネントがこれらのどのタグも持っていないときのみ、アビリティをアクティベートできます。 |
Target Required Tags | 対象のアクタまたはコンポーネントがこれらすべてのタグを持っている時のみアビリティをアクティベートできます。 |
Target Blocked Tags | 対象のアクタまたはコンポーネントがこれらのどのタグも持っていない時のみアビリティをアクティベートできます。 |
レプリケーション
ゲームプレイ アビリティは内部状態と ゲームプレイ イベント のレプリケーションや、レプリケーションを無効にしてネットワーク帯域幅と CPU サイクルの節約をサポートします。アビリティの ゲームプレイ アビリティ レプリケーション を「 Yes 」または「 No 」に設定することでアビリティが自身のインスタンスをレプリケートするか、状態をアップデートするか、ネットワーク越しにゲームプレイ イベントを送信するかを制御できます。アビリティがレプリケートするマルチプレイヤー ゲーム向けに、ゲームプレイ ネット実行ポリシー という、レプリケーション処理について次のようなオプションがあります。
-
Local Predicted: レスポンスの良さと精度のバランスを上手に取るオプションです。アビリティはクライアントが発行するコマンドのローカル クライアント上で直ちに実行されますが、最終決定権はサーバーにあり、アビリティへの実際のインパクトについてクライアントをオーバライドすることが可能です。クライアントは効率よくサーバーからのアビリティを実行するパーミッションをサーバーに求めるとともに、サーバーがクライアントの結果を承認しているかのようにローカルで処理します。クライアントはアビリティの振舞いをローカルで予測しているので、クライアントの予測がサーバーに拒否されない限り、非常にスムーズで遅延が発生しません。
-
Local Only: クライアントはアビリティを単純にローカル実行します。クライアントがアビリティをホスト上で使用しているか (物理サーバーマシン上でのプレイ)、シングル プレーヤー ゲームの場合、アビリティはサーバー上で実行されますが、サーバーへのレプリケーションは行われません。専用サーバーゲームは、そのサーバー機でプレイするクライアントがいないため、適用されません。このアビリティに影響を受けるものはすべて、サーバーから受信する可能性のある訂正も含め、通常のレプリケーション ルールが適用されます
-
Server Initiated: アビリティはサーバーで開始されクライアントに伝播します。クライアント視点においてサーバーで実際に起きていることに対してより正確なのですが、アビリティを使用するクライアントではローカルでの予想をしないことによる遅延が発生します。遅延はごくわずかであっても、とりわけ切迫したシチュエーションで高速動作するアクションのようなアビリティのタイプのなかには ローカル予想モードでのようにはスムーズに動作しないものもあります。
-
Server Only: 「サーバーのみ」のアビリティはサーバーで実行され、クライアントにはレプリケートされません。これらのアビリティの影響を受ける変数は通常通りレプリケートされます。つまり、サーバー権威型のデータはアビリティの影響を受けてクライアントに渡されますが、アビリティ自体はサーバーでのみ実行されます。
インスタンス化のポリシー
ゲームプレイ アビリティの実行時、実行中のアビリティを追跡するため (そのアビリティ型の) 新規オブジェクトがスポーンされます。バトル ロワイアル、 MOBA 、 MMO 、 RTS ゲームのような百を超えるプレーヤーと AI キャラクターの戦闘があるようなケースでは、アビリティが非常に高頻度に実行されることがあるため、アビリティ オブジェクトの高速生成によってパフォーマンスに悪影響が出ることがあります。これに対処するために、アビリティは、効率性と機能性をトレードオフにする 3 つのインスタンス化ポリシーのなかからの選択が可能です。以下 3 種類のインスタンス化をサポートします。
-
Instanced per Execution: アビリティが実行されるたびにアビリティのオブジェクトのコピーがスポーンされます。実行ごとにインスタンス化するメリットはブループリント グラフとメンバ変数の自由使用が可能で、実行開始時にすべてがデフォルト値に初期化されることです。最も単純な実装のインスタンス化ポリシーですが、アビリティが頻繁に実行されない場合のみ使用します。実行までに (通常 60 秒 から 90 秒の) 長いクールダウン時間を持ち、これらのアビリティを使用できるのはごく少数 (通常 10 人ほど) である MOBA の「 Ultimate 」 も使用事例の 1つと言えるかもしれません。数百のミニオンズがそれぞれ同時に基本攻撃を高頻度で実行し、新規オブジェクトを高速作成 (およびおそらくレプリケーション) するコンピュータ制御の「ミニオンズ」によって使用される基本攻撃アビリティは、対象にならないでしょう。
-
Instanced per Actor: 各アクタはアビリティの初回実行時にアビリティのインスタンスを1 つスポーンし、そのオブジェクトはその後の実行では再利用されます。これにより、アビリティの実行ごとにメンバ変数のクリーンナップ要求が生成されますが、複数実行間で情報を保持することも可能です。アクタごとのインスタンス化は、レプリケーションにとって理想的です。変数の変更の処理が可能なオブジェクトのレプリケートをアビリティが保持しますが、ネットワーク帯域幅や実行ごとに新規オブジェクトをスポーンする CPU 時間 を浪費しないためです。大規模シミュレーションにおいてこのポリシーはうまく動作します。(大規模バトルなど) アビリティを使用する多数のアクタが初回アビリティ使用時のみスポーンするからです。
-
Non-Instanced: 全カテゴリの中で一番効率の良いインスタンス化ポリシーです。アビリティ実行時にオブジェクトをスポーンしないかわりに、クラス デフォルト オブジェクト を使用します。しかし、この効率性にはいくつかの制限事項をともないます。まず、このポリシーにおいてのみ、アビリティがすべて C++ で書かれていることが必要です。ブループリント グラフ はオブジェクト インスタンスなしに作成できないからです。インスタンス化されないアビリティのブループリント クラスを作成することは可能ですが、エクスポーズされたプロパティのデフォルト値を変更することしかできません。さらに、C++ のネイティブ コード内でもメンバ変数の変更ができず、アビリティの実行中にデリゲートをバインドできず、アビリティによる変数のレプリケート や RPC の処理ができません。アビリティによる内部変数の保持 (ただしアビリティのユーザ上のアトリビュート設定は可能) とデータのレプリケートが不要な場合にのみ使用します。特に、大規模 RTS や MOBA タイトル中のユニットで使用される基本攻撃のように、頻繁に実行され、たくさんのキャラクターに使用されるアビリティに適しています。
ゲームプレイ イベントとのトリガー
Gameplay Events は、ゲームプレイ アビリティを直接トリガーするために、通常の経路を通過すること無くコンテクストのデータ ペイロードを送信可能なデータ構造です。Send Gameplay Event To Actor を呼び出し IAbilitySystemInterface
インターフェースを実装するアクタとゲームプレイ イベントに要求されたコンテクスト情報を提供するのが通常の方法ですが、Handle Gameplay Event をアビリティ システム コンポーネント上で直接呼び出すこともできます。これはゲームプレイ アビリティを呼び出す通常の手順ではないので、アビリティが必要とするコンテクスト情報は FGameplayEventData
データ構造によって渡されます。この構造は一般的なもので特定のゲームプレイ イベントやアビリティには拡張されませんが、どのような使用方法の要件も満たすはずです。ポリモーフィックな ContextHandle
フィールドが必要に応じて追加情報のサポートを提供します。
ゲームプレイ アビリティは、ゲームプレイ イベントによってトリガーされた時に、Activate Ability コードパス経由で実行されるのではなく、かわりに、パラメータとして追加コンテクスト データを提供する Activate Ability From イベントを使用します。アビリティをゲームプレイ イベントに反応させるためにはこのコード パスを処理させるようにします。しかし、Activate Ability From イベントがいったんゲームプレイ アビリティのブループリントに実装されると、自身の全アクティベーション トラフィックを取ってアクティブ アビリティを置換することにも留意してください。