はじめに
Unreal Engine (UE) Advent Calendar 2025 の10日目の記事です!
Gameplay Ability Blueprint の「Class Defaults > Details > Advanced」で「Instancing Policy」というものを選択することができます。

この Instancing Policy によってそのアビリティをどのタイミングでどのようにインスタンス化するのかを指定することができます。
この記事の執筆時点では「Non Instanced」と「Instanced Per Actor」、「Instanced Per Execution」の3つから選択できます。
この記事ではこれら3つの Instancing Policy の意味や挙動の違いなどについて解説します。
この記事での環境は以下の通りです。
- Windows 11
- UE 5.7.1(ランチャー版)
前述の3つの選択肢は GameplayAbilityTypes.h で EGameplayAbilityInstancingPolicy::Type として定義されています。
これらの列挙子の定義部分に書かれているコメントを表にまとめてみました。
| Instancing Policy 名 | コメント(原文) | コメント(和訳) |
|---|---|---|
| Non Instanced | This ability is never instanced. Anything that executes the ability is operating on the CDO. | このアビリティがインスタンス化されることはありません。そのアビリティを実行するものは全て CDO 上で動作します。 |
| Instanced Per Actor | Each actor gets it’s own single instance of this ability, which supports replication to its owning actor to allow RPC’s within the ability. As it is a single instance, only one ability maybe active at any time. State is saved between activations. | 各アクタはこのアビリティの単一のインスタンスを所有し、所有アクタへの複製をサポートすることでアビリティ内での RPC を可能にします。単一のインスタンスであるため、同時に発動できるアビリティは1つだけです。状態は発動間に保存されます。 |
| Instanced Per Execution | We instance this ability each time it is executed. Replication currently unsupported. These can have multiple running at the same time, and no state is saved between execution. | このアビリティは実行されるたびにインスタンス化されます。レプリケーションは現在サポートされていません。複数のインスタンスが同時に実行可能であり、実行間の状態は保存されません。 |
各 Instancing Policy の意味と挙動の違い
ここからは各 Instancing Policy の意味と挙動の違いについて解説します。
Non Instanced
まずは Non Instanced についてです。
Non Instanced は他の Instancing Policy と違い、そのアビリティを新たにインスタンス化することはありません。
代わりに CDO(Class Default Object)を使用します。
前述の通り、Non Instanced では新たにインスタンスを作成することがないので、パフォーマンス的には最も良い Instancing Policy なのですが、それゆえに他の Instancing Policy よりも制限が多く、UE 5.5 からは「非推奨」になりました。
As of UE 5.5, NonInstanced abilities are deprecated due to user error-proneness.
Gameplay Ability System – Best Practices for Setup
この記事では UE 5.7.1 を使用していますが、現時点では Instancing Policy を Non Instanced にしてコンパイルすると「Gameplay Ability Instancing Policy is NonInstanced which is deprecated. Use InstancedPerActor. Use CVar AbilitySystem.Fix.AllowNonInstancedAbilities to temporarily allow this during fixup.」というコンパイルエラーが発生してしまいます。

DefaultEngine.ini に以下の記述を追記するなどして「AbilitySystem.Fix.AllowNonInstancedAbilities」というコンソール変数を true にすると、このコンパイルエラーは発生しなくなります。
[SystemSettings]
AbilitySystem.Fix.AllowNonInstancedAbilities=True
が、公式ドキュメントの説明を読んでみると、やはり制限がかなりあるようなので後述の Instanced Per Actor や Instanced Per Execution を使用した方が良さそうです。
まず、このポリシーにおいてのみ、アビリティがすべて C++ で書かれていることが必要です。ブループリント グラフ はオブジェクト インスタンスなしに作成できないからです。インスタンス化されないアビリティのブループリント クラスを作成することは可能ですが、エクスポーズされたプロパティのデフォルト値を変更することしかできません。さらに、C++ のネイティブ コード内でもメンバ変数の変更ができず、アビリティの実行中にデリゲートをバインドできず、アビリティによる変数のレプリケート や RPC の処理ができません。
Unreal Engine でのゲームプレイ アビリティの使用
Instanced Per Actor / Instanced Per Execution
次は Instanced Per Actor と Instanced Per Execution についてです。
これらはその名前の通り、Instanced Per Actor はそのアビリティの所有アクタごとに、Instanced Per Execution はそのアビリティの発動ごとにインスタンス化されます。
少し調べてみたところ、パフォーマンス的にも Gameplay Ability System の設計思想的にも最も推奨されている Instancing Policy は Instanced Per Actor っぽいです。
This is the most common and aligns well with the design of GAS, meaning each actor has its own unique copy of the ability.
Mastering Gameplay Ability of GAS in Unreal Engine 5
This is the instancing policy that I would recommend for a lot of abilities.
Learning about Ability Instancing Policy in GAS
前述の通り、Instanced Per Execution はそのアビリティが発動されるたびにインスタンス化されるので、公式ドキュメントに記載されているようにあまり頻繁に発動されないアビリティに対して使用するのが良さそうです。
最も単純な実装のインスタンス化ポリシーですが、アビリティが頻繁に実行されない場合のみ使用します。
Unreal Engine でのゲームプレイ アビリティの使用
インスタンス化されるタイミングの違い
まずはそのアビリティがインスタンス化されるタイミングの違いを確認してみます。
UGameplayAbility を継承した「USampleGameplayAbility」というクラスを作成しました。
そのクラスのコンストラクタを定義して、「Called USampleGameplayAbility’s constructor.」というログを表示する処理を追加しました。
// .h
UCLASS()
class SAMPLE_API USampleGameplayAbility : public UGameplayAbility
{
GENERATED_BODY()
public:
USampleGameplayAbility(); //追加
};
// .cpp
USampleGameplayAbility::USampleGameplayAbility()
{
UKismetSystemLibrary::PrintString(this, TEXT("Called USampleGameplayAbility's constructor."));
}
コンストラクタはそのクラスがインスタンス化されたタイミングで呼び出されるので、これでこのクラスがインスタンス化されたタイミングを知ることができるようになりました。
そのクラスを親クラスとする「GA_Sample」という Gameplay Ability Blueprint を作成して、「Activate Ability」と表示する処理を ActivateAbility() に追加しました。

そのアビリティを所有するアクタ(BP_SampleActor)では、そのアビリティを Ability System Component に付与する際に「Give Ability」と表示するようにしました。

この状態で Instancing Policy を Instanced Per Actor にしてゲームを実行してみました。
すると、アクタにアビリティを付与したタイミングで「Called USampleGameplayAbility’s constructor.」と「Give Ability」が同時に表示され、その後はアビリティを発動するたびに「Activate Ability」のみが表示されました。

Instanced Per Actor ではそのアビリティをアクタに付与したタイミングでそのアビリティがインスタンス化されていることがわかります。
次は Instancing Policy を Instanced Per Execution にしてゲームを実行してみました。
すると、アクタにアビリティを付与したタイミングでは「Give Ability」のみが表示され、その後はアビリティを発動するたびに「Called USampleGameplayAbility’s constructor.」と「Activate Ability」が同時に表示されました。

Instanced Per Execution ではそのアビリティをアクタに付与したタイミングではなく、そのアビリティを発動したタイミングでインスタンス化されていることがわかります。
前回の状態を保持するかどうか
次は前回のアビリティ発動時の状態を保持するかどうかの違いについてです。
これを検証するためにアビリティのクラスで Guid 型の「Guid」という変数を追加しました。

ActivateAblity() は、その Guid 変数が有効なら(既に Guid が作成済みなら)「Existing Guid: {Guid 変数の値}」と表示して、そうでないなら Guid を新たに作成して「New Guid: {Guid 変数の値}」と表示するという内容に変更しました。

この状態で Instancing Policy を Instanced Per Actor にしてゲームを実行してみました。
すると、アビリティの初回発動時には「New Guid: {Guid 変数の値}」と表示され、2回目以降の発動時には「Existing Guid: {Guid 変数の値}」と表示されました。
表示された Guid は全て同じ値です。

Instanced Per Actor では前回のアビリティ発動時の状態を保持していることがわかります。
次は Instancing Policy を Instanced Per Execution にしてゲームを実行してみました。
すると、アビリティを発動するたびに「New Guid: {Guid 変数の値}」と表示されました。
表示された Guid は全て異なる値です。

Instanced Per Execution では前回のアビリティ発動時の状態を保持せず、アビリティの状態が毎回初期値にリセットされていることがわかります。
複数のアビリティを並行して発動している状態にできるかどうか
次は複数のアビリティを並行して発動している状態にできるかどうかを確認します。
ActivateAblity() では「Activate Ability」と表示した後に Delay で一定時間待機して「End Ability」と表示し、End Ability を呼び出すように変更しました。

そのアビリティの所有アクタでは、そのアビリティを発動する際にアビリティの発動に成功したなら「Activation Succeeded」、失敗したなら「Activation Failed」と表示するように変更しました。

この状態で Instancing Policy を Instanced Per Actor にしてゲームを実行してみました。
すると、アビリティの初回発動時には「Activate Ability」と「Activation Succeeded」と表示され、アビリティの発動に成功したことがわかります。
しかし、そのアビリティが終了する前(「End Ability」と表示される前)に再びアビリティを発動しようとすると「Activation Failed」と表示されました。
数秒待って「End Ability」と表示された後に再びアビリティを発動しようとすると今度は初回発動時のように「Activate Ability」と「Activation Succeeded」と表示され、アビリティの発動に成功したことがわかります。

このように Instanced Per Actor では複数のアビリティを並行して発動している状態にはできません。
次は Instancing Policy を Instanced Per Execution にしてゲームを実行してみました。
すると、アビリティの初回発動時に限らず、全ての発動時において「Activate Ability」と「Activation Succeeded」と表示され、アビリティの発動に成功したことがわかります。

このように Instanced Per Execution では複数のアビリティを並行して発動している状態にすることができます。
既に発動中のアビリティをキャンセルして再発動する方法の違い
最後は既に発動中のアビリティをキャンセルして再発動する方法の違いについてです。
先ほどは Instancing Policy を Instanced Per Actor にしたアビリティを発動中にそれを再発動させることができませんでしたが、Instancing Policy の下にある「Retrigger Instanced Ability」というプロパティにチェックを付けて true にするとそれができるようになります。

この Retrigger Instanced Ability のコメントを和訳すると「true かつ、既にアクティブなインスタンス化されたアビリティを再度発動しようとしたなら、それを終了させて再発動する。」となります。
試しに、アビリティが発動されるたびに Guid を新たに作成してその後はその Guid をひたすら毎フレーム表示し続けるように ActivateAblity() を修正しました。

そのアビリティの所有アクタでは先ほどと同様にそのアビリティを発動する際にアビリティの発動に成功したなら「Activation Succeeded」、失敗したなら「Activation Failed」と表示するような処理になっています。

この状態で Instancing Policy を Instanced Per Actor にし、Retrigger Instanced Ability にチェックを付けてゲームを実行してみました。
すると、2回目のアビリティ発動時、1回目のアビリティの Guid の表示が止まって新たな Guid と「Activation Succeeded」というログが表示されました。
LogBlueprintUserMessages: [GA_Sample_C_0] FBD07AA7435E4B0C6417B580E5AF0D18
LogBlueprintUserMessages: [BP_SampleActor_C_1] Activation Succeeded
LogBlueprintUserMessages: [GA_Sample_C_0] FBD07AA7435E4B0C6417B580E5AF0D18
≀
LogBlueprintUserMessages: [GA_Sample_C_0] FBD07AA7435E4B0C6417B580E5AF0D18
LogBlueprintUserMessages: [GA_Sample_C_0] 279E574043408FF594B7CCB9E2B678BF
LogBlueprintUserMessages: [BP_SampleActor_C_1] Activation Succeeded
1回目のアビリティがまだ発動中のタイミングでそのアビリティを再発動しようとすると、先ほどは「Activation Failed」と表示されて失敗してしまっていましたが、今回は「Activation Succeeded」と表示されて、アビリティの発動に成功したことがわかります。
次は Instanced Per Execution において、既に発動中のアビリティをキャンセルして再発動する方法について解説します。
こちらは簡単で「AssetTags (Default AbilityTags)」と同じタグを「Cancel Abilities with Tag」に設定すればいけます。

Instancing Policy を Instanced Per Execution にして、Retrigger Instanced Ability のチェックを外し、AssetTags と同じタグを Cancel Abilities with Tag に設定してゲームを実行してみました。
すると、アビリティを発動するたびに新たな Guid が表示され続けました。
LogBlueprintUserMessages: [GA_Sample_C_0] 138CFBAC4027888DD6E0728B92B0A573
LogBlueprintUserMessages: [BP_SampleActor_C_1] Activation Succeeded
LogBlueprintUserMessages: [GA_Sample_C_0] 138CFBAC4027888DD6E0728B92B0A573
≀
LogBlueprintUserMessages: [GA_Sample_C_0] 138CFBAC4027888DD6E0728B92B0A573
LogBlueprintUserMessages: [GA_Sample_C_1] 7F6F0E6D47099D8CFE1F4CAE861B790D
LogBlueprintUserMessages: [BP_SampleActor_C_1] Activation Succeeded
LogBlueprintUserMessages: [GA_Sample_C_1] 7F6F0E6D47099D8CFE1F4CAE861B790D
≀
LogBlueprintUserMessages: [GA_Sample_C_1] 7F6F0E6D47099D8CFE1F4CAE861B790D
LogBlueprintUserMessages: [GA_Sample_C_2] DB7D0FAF4DF8868757E7348A2C7A9FCC
LogBlueprintUserMessages: [BP_SampleActor_C_1] Activation Succeeded
LogBlueprintUserMessages: [GA_Sample_C_2] DB7D0FAF4DF8868757E7348A2C7A9FCC
≀
2回目以降のアビリティ発動時、もし既に発動中のアビリティがキャンセルされていないなら、既存の Guid と新たな Guid が1フレーム内で順番に表示されるはずですが、そのようにはなっていないので既に発動中のアビリティがしっかりキャンセルされていることがわかります。
最後に
参考記事
CDO(Class Default Object)
- UObjects, Generated Classes, and Class Default Objects (CDOs)
- What’s the class default object usage
- オブジェクト
Instancing Policy
- Unreal Engine でのゲームプレイ アビリティの使用
- UE4 GameplayAbility Pluginについてのメモ
- Gameplay Ability System – Best Practices for Setup
- Learning about Ability Instancing Policy in GAS
- Mastering Gameplay Ability of GAS in Unreal Engine 5
- Lyra Gameplay Abilities: retriggering an active ability?

