はじめに
Unreal Engine (UE) Advent Calendar 2025 の9日目の記事です!
(なんか空いてたので途中参戦しました。)
Gameplay Ability には「Cost Gameplay Effect Class」と「Cooldown Gameplay Effect Class」というプロパティがあるので、この記事ではそれらのプロパティを使用して Gameplay Ability にコストとクールダウンを実装する方法について解説します。
(Gameplay Attributes の入門記事です。)
この記事での環境は以下の通りです。
- Windows 11
- UE 5.7.1(ランチャー版)
サンプルプロジェクトの概要
この記事でいう「コスト」とは「アビリティを発動させるためにアクタが持っておくべきポイント」のことを指します。
この記事の手順通りに進めると、アビリティの Class Defaults でその値を「PointsRequiredToActivate」として設定できるようになります。

アクタはその値を「AvailablePoints」として持っており、その初期値は100になっています。
アビリティを発動するたびにアクタの AvailablePoints が PointsRequiredToActivate の値だけ減っていき、AvailablePoints が PointsRequiredToActivate 未満になるとアビリティを発動できなくなります。
また、この記事でいう「クールダウン」とは「アビリティを連続して発動させるのにかかる時間」のことを指します。
この記事の手順通りに進めると、PointsRequiredToActivate と同様にアビリティの Class Defaults でその値を「CooldownSeconds」として設定できるようになります。

PointsRequiredToActivate を20に、CooldownSeconds を1に、AvailablePoints の初期値を100にしてゲームを実行し、連続でアビリティを発動させようとするとこの GIF のようになります。
(この GIF では「Activated ability. Current AvailablePoints is {現在の AvailablePoints の値}.」というログを表示するという処理をアビリティの ActivateAbility() に追加してあります。)

この記事で作成するプロジェクトでは Enter キーを押すとアビリティが発動するようになっていて、この GIF では Enter キーをひたすら連打しているのですが、しっかり1秒以上間隔を空けてからアビリティが発動していることがわかります。
また、AvailablePoints の値が20ずつ減少していることもわかります。
この GIF では AvailablePoints が0になった後も Enter キーを連打しているのですが、その値が20未満になるとアビリティを発動できなくなっていることもわかります。
Gameplay Attributes と Gameplay Effect
この記事では Ability System Component や Gameplay Ability、Gameplay Tag などの他に「Gameplay Attributes」と「Gameplay Effect」というものが登場します。
Gameplay Attributes とは Gameplay Ability System において、そのアクタの状態を float 型の値として管理するものです。
例えばキャラクターの HP やスタミナ、レベル、アイテムの残りの使用回数などがそれにあたります。
また、Gameplay Attributes の値を変更する際は基本的に直接変数の値を変更するのではなく、Gameplay Effect 経由で変更します。
キャラクターの HP を10だけ減らしたいのなら、そのような効果を持つ Gameplay Effect を作成して、それを対象のキャラクターに適用するといったイメージです。
コストとクールダウンを実装してみる
ここからは実際にコストとクールダウンを実装してみます。
Attribute Set の作成
まずは Attribute Set を作成します。
先ほど説明したように Gameplay Attributes はそのアクタの状態を表すものでしたが、基本的にこの Gameplay Attributes は Attribute Set というクラスの中で定義します。
UAttributeSet を継承したクラスを作成します。
今回は「USampleAttributeSet」という名前にしました。
ヘッダーファイルとソースファイルにはそれぞれ以下のように書きます。
// .h
#pragma once
#include "CoreMinimal.h"
#include "AttributeSet.h"
#include "AbilitySystemComponent.h"
#include "SampleAttributeSet.generated.h"
UCLASS()
class SAMPLE_API USampleAttributeSet : public UAttributeSet
{
GENERATED_BODY()
public:
USampleAttributeSet();
UPROPERTY()
FGameplayAttributeData AvailablePoints;
ATTRIBUTE_ACCESSORS_BASIC(USampleAttributeSet, AvailablePoints)
};
// .cpp
#include "SampleAttributeSet.h"
USampleAttributeSet::USampleAttributeSet()
{
InitAvailablePoints(100.f);
}
今回は AvailablePoints という Gameplay Attributes を定義しました。
Gameplay Attributes を定義するときは FGameplayAttributeData という構造体を型とする変数を Attribute Set クラスで定義します。
ここで定義した Gameplay Attributes の値を読み書きする際は基本的にゲッターやセッターなどの関数を使用するのですが、ATTRIBUTE_ACCESSORS_BASIC() というマクロを使用するとそれらの関数を自動で生成してくれるので、「ATTRIBUTE_ACCESSORS_BASIC({クラス名}, {変数名})」と書いてそれらの関数を生成しています。
ATTRIBUTE_ACCESSORS_BASIC() によって InitAvailablePoints() という関数も生成されたので、Attribute Set のコンストラクタの中で AvailablePoints の初期値を100に設定しています。
これで Attribute Set を作成できました。
Attribute Set をアクタに持たせる
次は先ほど作成した Attribute Set をアクタに保持させます。
まずは対象のアクタのヘッダーファイルで USampleAttributeSet を前方宣言して USampleAttributeSet 型の変数を定義します。
今回は「SampleAttributeSet」という名前にしました。
(UAbilitySystemComponent 型の変数を定義していない場合は同様にして定義しておきます。)
// .h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "SampleActor.generated.h"
//追加
class UAbilitySystemComponent;
class USampleAttributeSet;
UCLASS()
class SAMPLE_API ASampleActor : public AActor
{
GENERATED_BODY()
public:
ASampleActor();
//追加
UPROPERTY(BlueprintReadOnly, EditDefaultsOnly)
TObjectPtr<UAbilitySystemComponent> AbilitySystemComponent;
//追加
UPROPERTY()
TObjectPtr<USampleAttributeSet> SampleAttributeSet;
protected:
virtual void BeginPlay() override;
public:
virtual void Tick(float DeltaTime) override;
};
ソースファイルではそのアクタのコンストラクタで Ability System Component と Attribute Set をインスタンス化してメンバ変数に保持します。
また、Attribute Set を定義したヘッダーファイルの include もしておきます。
BeginPlay() や Tick() には何も変更を加えていません。
// .cpp
#include "SampleActor.h"
#include "SampleAttributeSet.h" //追加
ASampleActor::ASampleActor()
{
PrimaryActorTick.bCanEverTick = true;
//追加
AbilitySystemComponent = CreateDefaultSubobject<UAbilitySystemComponent>(TEXT("AbilitySystemComponent"));
SampleAttributeSet = CreateDefaultSubobject<USampleAttributeSet>(TEXT("SampleAttributeSet"));
}
void ASampleActor::BeginPlay()
{
Super::BeginPlay();
}
void ASampleActor::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
これで Attribute Set をアクタに保持させることができました。
コストとクールダウン用の変数を Gameplay Ability に追加する
次はコストとクールダウン用の変数を Gameplay Ability に追加します。
UGameplayAbility を継承したクラスを作成します。
今回は「USampleGameplayAbility」という名前にしました。
ヘッダーファイルで以下のコードのようにして FScalableFloat 型の PointsRequiredToActivate 変数と CooldownSeconds 変数を定義します。
また、このクラスを継承した Gameplay Ability Blueprint でこれらの変数の初期値を設定できるように UPROPERTY() には EditDefaultsOnly を付けておきます。
// .h
#pragma once
#include "CoreMinimal.h"
#include "Abilities/GameplayAbility.h"
#include "SampleGameplayAbility.generated.h"
UCLASS()
class SAMPLE_API USampleGameplayAbility : public UGameplayAbility
{
GENERATED_BODY()
public:
//追加
UPROPERTY(EditDefaultsOnly)
FScalableFloat PointsRequiredToActivate;
//追加
UPROPERTY(EditDefaultsOnly)
FScalableFloat CooldownSeconds;
};
これでコストとクールダウン用の変数を Gameplay Ability に追加することができました。
Gameplay Mod Magnitude Calculation(GMMC)の作成
アビリティを発動するたびに AvailablePoints を減らしたり、クールダウンしたりする際は Gameplay Effect を使用するのですが、次はこの Gameplay Effect で使用する Gameplay Mod Magnitude Calculation(GMMC)を作成します。
UGameplayModMagnitudeCalculation を継承したクラスを作成します。
今回は「UGMMC_ConsumePoints」という名前にしました。
このクラスではアビリティを発動するたびに AvailablePoints をどれだけ減らすのかを計算します。
親クラスの CalculateBaseMagnitude_Implementation() をオーバーライドします。
// .h
#pragma once
#include "CoreMinimal.h"
#include "GameplayModMagnitudeCalculation.h"
#include "GMMC_ConsumePoints.generated.h"
UCLASS()
class SAMPLE_API UGMMC_ConsumePoints : public UGameplayModMagnitudeCalculation
{
GENERATED_BODY()
public:
//追加
virtual float CalculateBaseMagnitude_Implementation(const FGameplayEffectSpec& Spec) const override;
};
ソースファイルで CalculateBaseMagnitude_Implementation() に以下のような処理を追加します。
Spec という FGameplayEffectSpec 型の引数からは GetContext().GetAbility() で UGameplayAbility を取得できるので、それを USampleGameplayAbility に CastChecked() します。
これで PointsRequiredToActivate にアクセスできるようになったので、GetValue() で float 値を取得して返します。
// .cpp
#include "GMMC_ConsumePoints.h"
#include "SampleGameplayAbility.h" //追加
//追加
float UGMMC_ConsumePoints::CalculateBaseMagnitude_Implementation(const FGameplayEffectSpec& Spec) const
{
const USampleGameplayAbility* SampleAbility = CastChecked<USampleGameplayAbility>(Spec.GetContext().GetAbility());
return SampleAbility->PointsRequiredToActivate.GetValue();
}
同様にして UGMMC_Cooldown というクラスも作成して CalculateBaseMagnitude_Implementation() をオーバーライドし、CooldownSeconds の値を返すように修正します。
// .h
#pragma once
#include "CoreMinimal.h"
#include "GameplayModMagnitudeCalculation.h"
#include "GMMC_Cooldown.generated.h"
UCLASS()
class SAMPLE_API UGMMC_Cooldown : public UGameplayModMagnitudeCalculation
{
GENERATED_BODY()
public:
//追加
float CalculateBaseMagnitude_Implementation(const FGameplayEffectSpec& Spec) const override;
};
// .cpp
#include "GMMC_Cooldown.h"
#include "SampleGameplayAbility.h" //追加
//追加
float UGMMC_Cooldown::CalculateBaseMagnitude_Implementation(const FGameplayEffectSpec& Spec) const
{
const USampleGameplayAbility* SampleAbility = CastChecked<USampleGameplayAbility>(Spec.GetContext().GetAbility());
return SampleAbility->CooldownSeconds.GetValue();
}
これで Gameplay Effect に必要な GMMC を作成できました。
C++ が必要な作業はこれで終わりです。
プロジェクトをビルドして起動します。
Gameplay Effect の作成
次はコストとクールダウン用の Gameplay Effect を作成します。
Gameplay Effect を継承したブループリントクラスを2つ作成します。
今回は「GE_ConsumePoints」と「GE_Cooldown」という名前にしました。
GE_ConsumePoints を開いて各プロパティをこの画像のように変更します。

Duration Policy を「Instant」にすることで、この効果が一度だけ適用されるようにしています。
値を変更したい Gameplay Attributes を「Attribute」で指定しています。
Magnitude Calculation Type を「Custom Calculation Class」にすることで自作の GMMC を設定できるようにしています。
Coefficient は GMMC で計算した値に掛ける値のことで、これを -1 にすると減算になり、AvailablePoints の値を減らすことができます。
GE_ConsumePoints の設定は以上です。
次は GE_Cooldown を編集します。
Duration Policy を「Has Duration」にして、この効果の持続時間を設定できるようにします。
「Duration > Duration Magnitude > Magnitude Calculation Type」を「Custom Calculation Class」にして Calculation Class を「GMMC_Cooldown」にします。
Coefficient などは初期値のままで大丈夫です。

後にこの GE_Cooldown を Gameplay Ability の Cooldown Gameplay Effect Class に設定するのですが、このままではその際に「CooldownGameplayEffectClass ‘GE Cooldown’ grants no tags. A GameplayEffect class must grant tags (Component: Grant Tags to Target Actor) to be used as cooldown.」というコンパイルエラーが発生してしまいます。
なので GE_Cooldown の「Gameplay Effect > Components」に「Grant Tags to Target Actor」を追加して、クールダウン用のタグを Add to Inherited に設定します。

これでコストとクールダウン用の Gameplay Effect の作成が完了しました。
Gameplay Ability Blueprint の作成
次は先ほど作成した USampleGameplayAbility を親クラスとする Gameplay Ability Blueprint を作成します。
今回は「GA_Sample」という名前にしました。
「Class Defaults > Details > Sample Gameplay Ability」で PointsRequiredToActivate と CooldownSeconds の初期値を設定します。
今回は PointsRequiredToActivate を20に、CooldownSeconds を1にしました。

また、「Costs > Cost Gameplay Effect Class」に GE_ConsumePoints を、「Cooldowns > Cooldown Gameplay Effect Class」に GE_Cooldown を設定します。

ActivateAbility() には、「Activated ability. Current AvailablePoints is {現在の AvailablePoints の値}.」というログを表示するという処理や、End Ability を呼び出すという処理の他に「Commit Ability」を呼び出すという処理も追加します。

Commit Ability ではそのアビリティの所有者が必要なコストを持っているかどうかを確認したり、クールダウンを適用したりするので、Cost Gameplay Effect Class や Cooldown Gameplay Effect Class が設定されている Gameplay Ability は Commit Ability を呼び出す必要があります。
アビリティの付与と発動の処理の追加
最後はアビリティを付与したり、発動したりする処理を追加します。
Ability System Component や Attribute Set をインスタンス化する処理を追加したアクタを親クラスとするブループリントを作成します。
今回は「BP_SampleActor」という名前にしました。
先ほど作成した GA_Sample をアクタに付与する処理を BeginPlay() に、GA_Sample を発動する処理を DebugKeyEnter() に追加します。

これで Enter キーを押すと GA_Sample を発動できるようになりました。
テスト
作成したアクタをレベルに配置してゲームを実行し、Enter キーを連打してみます。
すると、アビリティが1秒以上間隔を空けないと発動できないようになっていて、アビリティを発動するたびに AvailablePoints が20ずつ減っていき、AvailablePoints が0になるとアビリティをそれ以上発動できないようになっていることがわかります。

本来、コストやクールダウンの処理を実装するには、そのアビリティを発動するのに必要なポイントと現在持っているポイントを比較して条件分岐させたり、その値を減らしたり、前回の発動時刻からの経過時間を計算して条件分岐したりといった処理を1から作る必要がありますが、Gameplay Ability System を利用するとかなり簡単に実装することができました!
最後に
参考
- [UE4]GameplayAbilitySystemで「スタミナ」を作る
- GAS最初の60分「2. Attribute Sets(属性セット)」
- ゲームプレイ アビリティ システム – セットアップのベスト プラクティス
- GameplayAttribute を BP だけで使いたい!
- Unreal Engine のゲームプレイ アビリティ システムのゲームプレイ エフェクト
- Unreal Engine でのゲームプレイ アトリビュートおよびアトリビュート セット






