ささみのメモ帳

ゲーム会社で働く、無能プログラマーが自分のためのメモ帳として利用しています。

UEのGASのTag追加方法メモ

Tagとは

UEのGameAbilitySystemの機能の一つで、ステータスのパラメータの種類や付与している効果の定義として利用できる。

タグを設定する上で以下の項目がある

Name(名前)

タグの名前で、階層名も兼ねてつけることができる

Comment(コメント)

タグについてのコメント,補足

Source(iniファイル名)

そのタグを管理するiniファイルの名前

Tagの定義/追加する方法は下記のような ものがある

前提条件

・GamePlayAbilities プラグインを導入済
・UE 5.1以降 ・Windows11

1.Editorでの設定

Project Settings > Project > GameplayTags を選択

Sourceの追加

Add new Gameplay Tag SourceでSourceの追加

Name:iniファイル名
※.ini記述無しでも正常に定義される
※この追加は ランタイム なものなので、iniファイルが生成されているわけではなく、タグを追加する際にiniファイルはされる

ConfigPath:iniファイルの配置ディレクト
※ConfigPathの追加方法は後に記載

Tagの追加

Manager Gameplay Tagsで左上の+よりタグの内容記入をして、AddNewTagで追加
※iniファイルが存在しない場合はこのタイミングで生成される。

Name:階層(.)も含めたタグ名
Comment:タグの説明、補足文
Soruce:タグを記録するSource(iniファイル)
※iniファイルが存在しなくても、Add new Gameplay Tag Sourceで定義したものは表示される

追加ができれば以下の様にしたの欄やファイルで確認可能

2.データテーブル

通常通りEditorにてデータテーブルの作成
デーブル構造はGameplayTagTableRowで作成

カラムはTagとCommentで、下記の様にタグとそのコメントを設定

Project Settings > Project > GameplayTags を選択

GamplayTagTableListに作成したデータテーブルを設定

SourceはiniファイルではなくDataTableになり、 テーブル内容でタグとコメントがつくられる。

3.iniファイルの手動作成

ConfigPathに設定されているディレクトリ(初期はConfig/Tags) に以下のような内容のiniファイルを自作して配置

Test.ini

[/Script/GameplayTags.GameplayTagsList]
GameplayTagList=(Tag="Test.Attack",DevComment="攻撃タグ")

4.モジュールの初期読み込み

こちら https://docs.unrealengine.com/4.27/ja/ProgrammingAndScripting/ProgrammingWithCPP/ModuleQuickStart/ を参考に、独自のモジュールを用意する モジュールクラスのStartupModuleにて、以下の様にAddNativeGameplayTagでTagを追加
二バイト文字のコメントはエラーになる場合があるので注意
TagSetModule.cpp

void FTagSetModule::StartupModule()
{
    //NativeGameplayTagsの登録
    //<タグ名、タグの説明>
    TTuple<FName, FString> tags[] = {
        {FName("Player.Attack"), FString("Player Attack")},
        {FName("Player.Defence"), FString("Player Defence")},
        {FName("Enemy.Attack"), FString("Enemy Attack")},
        {FName("Enemy.Defence"), FString("Enemy Defence")}
    };

    for (auto tag : tags)
    {
        UGameplayTagsManager::Get().AddNativeGameplayTag(tag.Key, tag.Value);
    }
}

これによって追加されたタグはiniやDataTable内容ではなく、コードによるついかになるため、ソース部分はNativeになる

5.AssetManagerの初期読み込み

以下のような独自のAssetManagerクラスを作成

UCLASS()
class TEST_API UTestAssetManager : public UAssetManager
{
    GENERATED_BODY()
public:
    static UTestAssetManager& Get();

protected:
    virtual void StartInitialLoading() override;
};

以下の様にStartInitialLoadingの内容に、AddNativeGameplayTagでTagを追加

void UTestAssetManager::StartInitialLoading()
{
    Super::StartInitialLoading();

    //NativeGameplayTagsの登録
    //<タグ名、タグの説明>
    TTuple<FName, FString> tags[] = {
        {FName("Player.Attack"), FString("Player Attack")},
        {FName("Player.Defence"), FString("Player Defence")},
        {FName("Enemy.Attack"), FString("Enemy Attack")},
        {FName("Enemy.Defence"), FString("Enemy Defence")}
    };

    for (auto tag : tags)
    {
        UGameplayTagsManager::Get().AddNativeGameplayTag(tag.Key, tag.Value);
    }
}

DefaultEngine.iniの[/Script/Engine.Engine]にて独自のAssetManagerを定義

[/Script/Engine.Engine]
AssetManagerClassName=/Script/[ModuleName].[AssetManagerName]
//例
AssetManagerClassName=/Script/GAS_Test.GASTestAssetManager

これによって追加されたタグはiniやDataTable内容ではなく、コードによるついかになるため、ソース部分はNativeになる

5.シングルトンの初期読み込み

Nativeの場合、AssetManager#StartInitialLoadingやStartupModuleよりも先にコンストラクタの処理が走ってしまう場合があります。
そのような場合には、シングルトンによる初回初期化のものを作って利用するのが対策の一つ

NativeTags.h

#pragma once

#include "GameplayTagContainer.h"

/**
 * iniファイルを生成しない、ネイティブなゲームプレイタグ
 * ネイティブ用のシングルトン
 */

struct FNativeTags
{
private:
    static FNativeTags Instance;

public:
    static const FNativeTags& Get() 
    { 
        if (!Instance.bIsInstantceCreated)[[unlikely]]
        {
            Instance.InitializeNativeGameplayTags();
            Instance.bIsInstantceCreated = true;
        }
        return Instance; 
    }
    
    FGameplayTag FireWait;
    FGameplayTag Hit;

    FGameplayTag Reload;
    
private:
    void InitializeNativeGameplayTags();
    
    bool bIsInstantceCreated = false;
};

NativeTags.cpp

#include "NativeTags.h"
#include "GameplayTagsManager.h"

FNativeTags FNativeTags::Instance;

void FNativeTags::InitializeNativeGameplayTags()
{
    UGameplayTagsManager& Manager = UGameplayTagsManager::Get();
    Instance.FireWait = Manager.AddNativeGameplayTag(FName("Player.FireWait"), FString("wait until ready to fire"));
    Instance.Hit = Manager.AddNativeGameplayTag(FName("Projectile.Hit"), FString("projectile contact to actor"));

    Instance.Reload = Manager.AddNativeGameplayTag(FName("GameplayCue.Player.Reload"), FString("replenishment of ammunition"));
}

おまけ

ConfigPathの追加

UGameplayTagsManager#AddTagIniSearchPathを利用することで、 iniファイルの検索場所(ConfigPath)の追加が可能

フルパスにしなかった場合、
Program Files\Epic Games\UE_[version]\Engine\Binaries\Win64
の中に生成されるため、フルパスにする必要あり

以下はStartupModuleを利用した場合
ConfigPathModule.cpp

void FConfigPathModule::StartupModule()
{
    //ConfigPathの登録
    UGameplayTagsManager::Get().AddTagIniSearchPath(FString("D:/UE_Project/GAS_Test/Sample1"));
    UGameplayTagsManager::Get().AddTagIniSearchPath(FString("D:/UE_Project/GAS_Test/Sample2"));
}