mcpField
U
ue-game-features

ue-game-features

github.com/quodsoler開発4191.1k 回インストール4 週間前に更新
リポジトリ

ue-game-features について

UE 5.8 の Game Features と Modular Gameplay を扱う開発者向けのリファレンススキルです。プラグイン設定、状態管理、アクション、コンポーネント注入に関する検証済み API を整理しています。

主な機能

  1. 01Game Feature プラグイン構成と記述子
  2. 02プラグイン状態とサブシステム制御
  3. 03カスタム Game Feature Action
  4. 04Actor へのコンポーネント注入
  5. 05初期化状態システムとプロジェクトポリシー

活用シーン

  1. 01独立してロードできるゲーム機能プラグインの作成
  2. 02実行時の機能ロード、アクティブ化、アンロード
  3. 03機能の開始・停止処理の実装
  4. 04モジュール型コンポーネントの初期化調整

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/quodsoler/unreal-engine-skills --skill ue-game-features

インストール後、Claude Code で/ue-game-featuresを入力して読み込まれたか確認します。

同梱ファイルreferences/experience-system.mdreferences/game-feature-patterns.md

詳細

UE Game Features と Modular Gameplay

対象エンジン:UE 5.8。以下の API は 5.8 のヘッダーに照らして検証済みです。旧形式は「非推奨 — 使用しないでください」に記載しています。

Game Features(5.8 でベータ)は、ゲームプレイを Plugins/GameFeatures/ 配下の自己完結型プラグインとしてパッケージ化します。UGameFeaturesSubsystem(UEngineSubsystem)はステートマシンを通じて各プラグインを制御します。プラグイン内の UGameFeatureData プライマリデータアセットには、登録、ロード、有効化、無効化の際に実行される UGameFeatureAction オブジェクトのインスタンス化リストが格納されています。Modular Gameplay(5.8 でベータ)は、オプトインしたアクターにコンポーネントを注入する UGameFrameworkComponentManager(UGameInstanceSubsystem)に加え、独立してロードされるフィーチャー間の初期化順序を制御する UGameFrameworkComponent の基底クラス群と初期化状態システムを提供します。Build.cs のモジュールは GameFeatures と ModularGameplay です。GameFeatures モジュールは ModularGameplay と DataRegistry にすでにパブリック依存しているため、アクションのみを利用するコードでは GameFeatures だけで十分です。

コンテキスト

.agents/ue-project-context.md が存在する場合は読み込んでください(モジュール名、規約、有効なプラグイン、GAS/ネットワーク設定)。ファイルがない場合も処理を続けてください。

リクエストとコードベースから該当する領域を特定してください。解釈が 2 通りあり、それぞれで異なるコードになる場合に限り、質問してください。

リクエストの内容…参照先
フィーチャープラグインの作成、.uplugin のキー、フォルダ構成、UGameFeatureDataプラグインの構成と記述子
実行時のフィーチャーの有効化またはアンロード、プラグイン URL、プラグインの状態プラグインの状態とサブシステム
フィーチャーの有効化時または無効化時に実行されるアクションの作成UGameFeatureAction の作成
アクションを自作せず、既製のものを選ぶエンジン提供のアクション
フィーチャーからアクターへのコンポーネント追加、拡張イベントコンポーネントの注入
別々にロードされるコンポーネント間の初期化順序の制御初期化状態システム
Pawn/Controller/PlayerState/GameState コンポーネントの基底クラスの選択モジュラーコンポーネントの基底クラス
ロードするプラグインのフィルタリング、クライアント/サーバーデータ、状態オブザーバープロジェクトポリシーとオブザーバー
Lyra 形式のエクスペリエンス構成(エンジン API ではなくサンプルコード)references/experience-system.md
完全なテンプレート:カスタムアクション、レシーバーの設定、ポリシーのサブクラスreferences/game-feature-patterns.md

プラグインのレイアウトと記述子

Game Feature プラグインは、<Project>/Plugins/GameFeatures/ または <AdditionalPluginDirectory>/GameFeatures/ に配置される通常のプラグインです。この配置場所によって Game Feature プラグインかどうかが決まります。UGameFeaturesSubsystemSettings::IsValidGameFeaturePlugin は、記述子のパスがこれらのフォルダーに一致するかを判定します。.uplugin スキーマにプラグインレベルの "Type" キーはありません。

Plugins/GameFeatures/
├── MyFeature/
│   ├── MyFeature.uplugin
│   ├── Content/MyFeature.uasset        (UGameFeatureData, named after the plugin)
│   └── Source/MyFeatureRuntime/
└── MyFeatureRules/
    ├── MyFeatureRules.uplugin
    └── Content/MyFeatureRules.uasset
{
	"FileVersion": 3,
	"Version": 1,
	"VersionName": "1.0",
	"FriendlyName": "My Feature",
	"Description": "Adds my gameplay feature",
	"Category": "Game Features",
	"CreatedBy": "",
	"CanContainContent": true,
	"ExplicitlyLoaded": true,
	"BuiltInInitialFeatureState": "Active",
	"Modules": [
		{ "Name": "MyFeatureRuntime", "Type": "Runtime", "LoadingPhase": "Default" }
	],
	"Plugins": [
		{ "Name": "GameFeatures", "Enabled": true },
		{ "Name": "ModularGameplay", "Enabled": true }
	]
}
キー意味
ExplicitlyLoadedプラグインマネージャーは起動時にプラグインをマウントせず、機能のステートマシンがマウントとアンマウントを行います。機能プラグインでは常に true です。
CanContainContentプラグインに Content/ ディレクトリが含まれます(UGameFeatureData アセットに必要です)。
BuiltInInitialFeatureStateビルトインプラグインが起動時にどの段階まで進むかを指定します。"Installed"、"Registered"、"Loaded"、"Active" のいずれかです。不明な値を指定するとエラーがログに記録され、Active にフォールバックします。
EnabledByDefault.uproject にエントリーがなくてもプラグインを有効にします。
Modules[].TypeModuleHostType の名前です。Runtime、RuntimeNoCommandlet、Editor、Developer、Program などがあります。
Modules[].LoadingPhaseModuleLoadingPhase の名前です。Default、PreDefault、PostConfigInit、PostEngineInit などがあります。

コンテンツのみの機能プラグインでは、Modules を完全に省略します。モジュールを追加するには、Build.cs を追加します。詳しくは ue-module-build-system を参照してください。

UGameFeatureData

UGameFeatureData : UPrimaryDataAsset は、サブシステムがプラグイン用に読み込むアセットです。アセットで設定する 2 つのプロパティは保護されているため、アクセサーを通じて読み取ります。

const TArray<UGameFeatureAction*>& FeatureActions = FeatureData->GetActions();
const TArray<FPrimaryAssetTypeInfo>& ScanTypes = FeatureData->GetPrimaryAssetTypesToScan();

Actions は、アセット内にインラインで作成される UGameFeatureAction のサブクラスの Instanced 配列です。PrimaryAssetTypesToScan は、機能の登録時にプラグイン内のどのプライマリアセットタイプをスキャンするかをアセットマネージャーに指示します。詳しくは ue-data-assets-tables を参照してください。

GetPrimaryAssetTypesToScan を変更する場合、またはエディターで GetDisallowedActions を変更する場合に限り、UGameFeatureData をサブクラス化してください。

プラグインの状態とサブシステム

遷移状態とエラー状態は遷移先状態の間に位置し、遷移先状態は完全に順序付けられています。EGameFeaturePluginState は、GAME_FEATURE_PLUGIN_STATE_LIST マクロから生成された通常の列挙型です。

遷移先状態意味
Terminalステートマシンが削除される前の最終状態です。
UnknownStatusURL のみが判明しています。
StatusKnown利用可能であることが確認されています(ディスク上またはバンドル内)。
Uninstalledプラグインのローカルデータが削除されています。
Installedファイルはローカルストレージにありますが、登録されていません。
Registeredアセットが検出および登録され、アクションが OnGameFeatureRegistering を受け取りました。
Loadedプラグインのコードとコンテンツはメモリ内にありますが、まだゲームに影響していません。
Activeアクションが適用され、機能がゲームに影響しています。

ログと GetPluginState の結果に表示される遷移状態には、CheckingStatus、Downloading、Mounting、Registering、Loading、ActivatingDependencies、Activating、Deactivating、Unloading、Unregistering、Unmounting、Releasing、Uninstalling と、対応する Error* 状態があります。

その他に 2 つの列挙型があります。EGameFeatureTargetState(Installed、Registered、Loaded、Active)は ChangeGameFeatureTargetState に渡す値です。EBuiltInAutoState(Invalid、Installed、Registered、Loaded、Active)は BuiltInInitialFeatureState の解析先です。

コードからプラグインを操作する
#include "GameFeaturesSubsystem.h"

void UMyFeatureManager::EnableMyFeature()
{
    UGameFeaturesSubsystem& GFS = UGameFeaturesSubsystem::Get();

    FString PluginURL;
    if (!GFS.GetPluginURLByName(TEXT("MyFeature"), PluginURL))
    {
        UE_LOG(LogMyGame, Error, TEXT("MyFeature is not a discovered game feature plugin"));
        return;
    }

    GFS.LoadAndActivateGameFeaturePlugin(PluginURL,
        FGameFeaturePluginLoadComplete::CreateUObject(this, &UMyFeatureManager::HandleFeatureLoaded));
}

void UMyFeatureManager::HandleFeatureLoaded(const UE::GameFeatures::FResult& Result)
{
    if (Result.HasError())
    {
        UE_LOG(LogMyGame, Error, TEXT("MyFeature failed: %s"), *Result.GetError());
    }
}

GetPluginURLByName(FStringView PluginName, FString& OutPluginURL)は、組み込みプラグインのURLを安全に構築する方法です。静的ビルダーUGameFeaturesSubsystem::GetPluginURL_FileProtocol(PluginDescriptorPath)とGetPluginURL_InstallBundleProtocol(PluginName, BundleName)は、それぞれfile:とinstallbundle:のURL(EGameFeaturePluginProtocol::File、::InstallBundle)を生成します。

呼び出し効果
LoadGameFeaturePlugin(URL, CompleteDelegate)Loadedに進みます。
LoadAndActivateGameFeaturePlugin(URL, CompleteDelegate)Activeに進みます。
RegisterGameFeaturePlugin(URL, CompleteDelegate)Registeredに進みます。
ChangeGameFeatureTargetState(URL, EGameFeatureTargetState::Registered, CompleteDelegate)任意の遷移先状態に移行します。
DeactivateGameFeaturePlugin(URL)Loadedまで戻ります。
UnloadGameFeaturePlugin(URL, /*bKeepRegistered=*/ false)RegisteredまたはInstalledまで戻ります。
TerminateGameFeaturePlugin(URL)状態マシンを終了します。
CancelGameFeatureStateChange(URL)進行中の遷移を中止します。

上記の完了デリゲートはすべてFGameFeaturePluginChangeStateCompleteのエイリアス、つまりDECLARE_DELEGATE_OneParam(..., const UE::GameFeatures::FResult&)です。TConstArrayView<FString> PluginURLsを受け取るオーバーロードは、TDelegate<void(const TMap<FString, UE::GameFeatures::FResult>&)>であるFMultipleGameFeaturePluginsLoadedを通じて結果を報告します。

クエリ:GetPluginState(URL)、IsGameFeaturePluginActive(URL, bCheckForActivating)、IsGameFeaturePluginActiveByName(PluginName, bCheckForActivating)、IsGameFeaturePluginRegistered(URL, bCheckForRegistering)、IsGameFeaturePluginLoaded(URL)、IsGameFeaturePluginInErrorState(URL)、GetActivePluginNames()。

テスト用コンソールコマンド(GameFeaturesSubsystem.cpp:583-661、プラグイン名またはURLを指定します):ListGameFeaturePlugins [-activeonly] [-csv]、LoadGameFeaturePlugin、DeactivateGameFeaturePlugin、UnloadGameFeaturePlugin、ReleaseGameFeaturePlugin、CancelGameFeaturePlugin、TerminateGameFeaturePlugin。LoadGameFeaturePluginコンソールコマンドはLoadAndActivateGameFeaturePluginを呼び出し、ECVF_Cheatです。同名のC++関数はLoadedまでしか進みません。

UGameFeatureActionの作成

UGameFeatureActionはUObjectを継承するUCLASS(MinimalAPI, DefaultToInstanced, EditInlineNew, Abstract)です。DefaultToInstancedとEditInlineNewにより、Actions配列内にインラインでインスタンスを作成できます。オーバーライド可能な仮想関数をそのまま示します。

virtual void OnGameFeatureRegistering() {}
virtual void OnGameFeatureUnregistering() {}
virtual void OnGameFeatureLoading() {}
virtual void OnGameFeatureUnloading() {}
virtual void OnGameFeatureActivating(FGameFeatureActivatingContext& Context);
virtual void OnGameFeatureActivating() {}
virtual void OnGameFeatureActivated() {}
virtual void OnGameFeatureDeactivating(FGameFeatureDeactivatingContext& Context) {}

コンテキスト版のOnGameFeatureActivatingをオーバーライドしてください。基底クラスの実装は、そちらから引数なし版を呼び出すため、両方をオーバーライドするとコードが2回実行されます。IsDataValidはUGameFeatureActionのメンバーではなく、UObjectのオーバーライドであり、エディター専用です。

// MyGameFeatureAction_GrantTag.h
#pragma once

#include "GameFeatureAction.h"
#include "GameplayTagContainer.h"
#include "MyGameFeatureAction_GrantTag.generated.h"

struct FGameFeatureActivatingContext;
struct FGameFeatureDeactivatingContext;
struct FWorldContext;

UCLASS(meta = (DisplayName = "My Grant Tag"))
class MYGAME_API UMyGameFeatureAction_GrantTag : public UGameFeatureAction
{
    GENERATED_BODY()

public:
    virtual void OnGameFeatureActivating(FGameFeatureActivatingContext& Context) override;
    virtual void OnGameFeatureDeactivating(FGameFeatureDeactivatingContext& Context) override;

#if WITH_EDITOR
    virtual EDataValidationResult IsDataValid(class FDataValidationContext& Context) const override;
#endif

    UPROPERTY(EditAnywhere, Category = "Tags")
    FGameplayTag TagToGrant;

private:
    void ApplyToWorld(const FWorldContext& WorldContext);
};

アクションのインスタンスは、そのフィーチャーが適用されるすべてのワールドで共有されるため、ワールドごとの状態を単純なメンバーに保持しないでください。コンテキストでワールドを絞り込み、FObjectKeyをキーにして状態を管理します。

void UMyGameFeatureAction_GrantTag::OnGameFeatureActivating(FGameFeatureActivatingContext& Context)
{
    for (const FWorldContext& WorldContext : GEngine->GetWorldContexts())
    {
        if (Context.ShouldApplyToWorldContext(WorldContext))
        {
            ApplyToWorld(WorldContext);
        }
    }
}

FGameFeatureActivatingContextとFGameFeatureDeactivatingContextはどちらもFGameFeatureStateChangeContextを継承します。このクラスは、ShouldApplyToWorldContext(const FWorldContext&)、ShouldApplyUsingOtherContext(const FGameFeatureStateChangeContext&)、SetRequiredWorldContextHandle(FName)を提供します。

非同期処理が必要な無効化では、状態マシンが開いたままになるようにする必要があります。FGameFeatureDeactivatingContext::PauseDeactivationUntilComplete(FString InPauserTag)はFSimpleDelegateを返します。すべての経路で、ゲームスレッド上からこのデリゲートを実行する必要があります。

void UMyGameFeatureAction_GrantTag::OnGameFeatureDeactivating(FGameFeatureDeactivatingContext& Context)
{
    FSimpleDelegate Resume = Context.PauseDeactivationUntilComplete(TEXT("MyGrantTag_Cleanup"));
    StartAsyncCleanup(Resume);   // must call Resume.ExecuteIfBound() when finished
}

ワールド追跡やRAIIハンドルのパターンを含む完全なテンプレートは、references/game-feature-patterns.mdにあります。

エンジン提供のアクション

アクション目的
UGameFeatureAction_AddComponentsアクター↔コンポーネントのスポーン要求を UGameFrameworkComponentManager に追加します。
UGameFeatureAction_AddCheats各プレイヤーにチートマネージャー拡張を追加します。
UGameFeatureAction_AddActorFactoryプラグインの登録時にアクターファクトリーを登録します。
UGameFeatureAction_AddChunkOverrideプラグインのアセットを指定されたチャンク ID にクックします。
UGameFeatureAction_AddWPContentWorld Partition のコンテンツをコンテンツバンドルとして追加します。
UGameFeatureAction_AddWorldPartitionContentプラグインの World Partition コンテンツを追加します。
UGameFeatureAction_DataRegistryData Registry のリストを読み込み、初期化します。
UGameFeatureAction_DataRegistrySource既存の Data Registry にソースアセットを追加します。
UGameFeatureAction_AudioActionBaseオーディオエンジンに影響するアクションの Abstract 基底クラスです。
UIrisFilterGameFeatureActionIris ネットワークフィルターを作成します。

ほとんどの機能で必要になるのは UGameFeatureAction_AddComponents です。これは TArray<FGameFeatureComponentEntry> ComponentList を保持し、各 FGameFeatureComponentEntry には TSoftClassPtr<AActor> ActorClass(meta=(AllowAbstract="True"))、TSoftClassPtr<UActorComponent> ComponentClass、ビットフィールド uint8 bClientComponent:1 と uint8 bServerComponent:1、および uint8 AdditionFlags(meta=(Bitmask, BitmaskEnum="/Script/ModularGameplay.EGameFrameworkAddComponentFlags"))が含まれます。

どこでも必要なコンポーネントには bClientComponent と bServerComponent の両方を設定し、権威的なゲームプレイロジックにはサーバーのみ、コスメティック用途にはクライアントのみを設定します。このアクションはゲームインスタンスごとに TSharedPtr<FComponentRequestHandle> を保持し、無効化時に破棄します。これにより、注入されたコンポーネントが削除されます。

コンポーネントの注入

UGameFrameworkComponentManager は UGameInstanceSubsystem です。アクターから取得します。

#include "Components/GameFrameworkComponentManager.h"

UGameFrameworkComponentManager* CompMgr = UGameFrameworkComponentManager::GetForActor(MyActor);

GetForActor(const AActor* Actor, bool bOnlyGameWorlds = true) は、ゲームワールドの外では null を返します。ゲームインスタンスを取得できる場合は、GetGameInstance()->GetSubsystem<UGameFrameworkComponentManager>() も使用できます。

レシーバー

アクターが注入されたコンポーネントを受け取るには、まず自分自身を登録する必要があります。

void AMyCharacter::BeginPlay()
{
    Super::BeginPlay();
    UGameFrameworkComponentManager::AddGameFrameworkComponentReceiver(this);
}

void AMyCharacter::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
    UGameFrameworkComponentManager::RemoveGameFrameworkComponentReceiver(this);
    Super::EndPlay(EndPlayReason);
}

静的ヘルパーはアクターに対応するマネージャーを解決し、AddReceiver(AActor* Receiver, bool bAddOnlyInGameWorlds = true) と RemoveReceiver(AActor* Receiver) に処理を転送します。これらはマネージャーから直接呼び出すこともできます。

リクエストと拡張ハンドラー
TSharedPtr<FComponentRequestHandle> RequestHandle = CompMgr->AddComponentRequest(
    TSoftClassPtr<AActor>(AMyCharacter::StaticClass()),
    UMyHealthComponent::StaticClass(),
    EGameFrameworkAddComponentFlags::AddUnique);

FComponentRequestHandle は RAII です。注入を続けたい間は保持し、リクエストと、リクエストによって作成されたコンポーネントを削除するときに破棄します。また、IsValid() も公開しており、所有するマネージャーがなくなると false を返します。

EGameFrameworkAddComponentFlags値動作
None0レシーバーに常にコンポーネントを作成します。
AddUnique0b00000001レシーバーに同じクラスのコンポーネントがすでにある場合はスキップします。
AddIfNotChild0b00000010要求されたクラスが既存のコンポーネントのクラスの子クラスである場合はスキップします。
UseAutoGeneratedName0b00000100クラス名を再利用せず、新しい名前を生成します。

拡張ハンドラーはコンポーネントを追加するのではなく、レシーバーを監視します。デリゲートはマネージャー内で次のように宣言されています:DECLARE_DELEGATE_TwoParams(FExtensionHandlerDelegate, AActor*, FName)

ExtensionHandle = CompMgr->AddExtensionHandler(
    TSoftClassPtr<AActor>(AMyCharacter::StaticClass()),
    UGameFrameworkComponentManager::FExtensionHandlerDelegate::CreateUObject(
        this, &UMyFeatureManager::HandleActorExtension));
void UMyFeatureManager::HandleActorExtension(AActor* Actor, FName EventName)
{
    if (EventName == UGameFrameworkComponentManager::NAME_GameActorReady)
    {
        // Actor has finished its default initialization
    }
}

5 つの static FName イベント定数は、NAME_ReceiverAdded、NAME_ReceiverRemoved、NAME_ExtensionAdded、NAME_ExtensionRemoved、および NAME_GameActorReady です。独自のイベントは、CompMgr->SendExtensionEvent(Receiver, EventName, bOnlyInGameWorlds) または静的関数 UGameFrameworkComponentManager::SendGameFrameworkComponentExtensionEvent(Receiver, EventName, bOnlyInGameWorlds) で送信します。

初期化状態システム

初期化状態を使うと、異なるプラグインから追加されるコンポーネントの初期化順序を解決できます。状態は FGameplayTag の値で、マネージャーに順番に登録します。タグ自体の宣言方法については、ue-gameplay-tags-messaging を参照してください。

CompMgr->RegisterInitState(TAG_InitState_Spawned, false, FGameplayTag());
CompMgr->RegisterInitState(TAG_InitState_DataAvailable, false, TAG_InitState_Spawned);
CompMgr->RegisterInitState(TAG_InitState_DataInitialized, false, TAG_InitState_DataAvailable);
CompMgr->RegisterInitState(TAG_InitState_GameplayReady, false, TAG_InitState_DataInitialized);

RegisterInitState(FGameplayTag NewState, bool bAddBefore, FGameplayTag ExistingState) は既存の状態を基準に挿入するため、エンジンには固定の状態リストはありません。状態リストはプロジェクト側で管理します。状態は一度だけ登録してください。たとえば、UGameInstanceSubsystem やプロジェクトのポリシークラスから登録できます。

マネージャーの呼び出し用途
ChangeFeatureInitState(Actor, FeatureName, Implementer, FeatureState)1 つのフィーチャーを次の状態に進めます。bool を返します。
GetInitStateForFeature(Actor, FeatureName)現在の状態タグを取得します。
HasFeatureReachedInitState(Actor, FeatureName, FeatureState)1 つのフィーチャーが指定の状態に到達しているか確認します。
HaveAllFeaturesReachedInitState(Actor, RequiredState, ExcludingFeature)アクター全体を確認します。
IsInitStateAfterOrEqual(FeatureState, RelativeState)登録順に基づいて 2 つのタグを比較します。
GetImplementerForFeature(Actor, FeatureName, RequiredState)フィーチャーを実装するオブジェクトを検索します。
RegisterAndCallForActorInitState(Actor, FeatureName, RequiredState, Delegate, bCallImmediately)1 つのアクターの状態を待機します。FDelegateHandle を返します。
RegisterAndCallForClassInitState(ActorClass, FeatureName, RequiredState, Delegate, bCallImmediately)クラスのすべてのアクターの状態を待機します。FDelegateHandle を返します。
UnregisterActorInitStateDelegate(Actor, Handle) / UnregisterClassInitStateDelegate(ActorClass, Handle)ネイティブバインディングを解除します(FDelegateHandle& を受け取ります)。

ネイティブデリゲートは DECLARE_DELEGATE_OneParam(FActorInitStateChangedDelegate, const FActorInitStateChangedParams&) です。FActorInitStateChangedParams は、OwningActor、FeatureName、Implementer、FeatureState を持つ USTRUCT です。

IGameFrameworkInitStateInterface

コンポーネントに IGameFrameworkInitStateInterface(UINTERFACE UGameFrameworkInitStateInterface、NotBlueprintable)を実装すると、標準の進行処理を利用できます。オーバーライドする価値のある仮想関数は、ヘッダーからそのまま引用すると次のとおりです。

virtual FName GetFeatureName() const { return NAME_None; }
virtual bool CanChangeInitState(UGameFrameworkComponentManager* Manager, FGameplayTag CurrentState, FGameplayTag DesiredState) const { return true; }
virtual void HandleChangeInitState(UGameFrameworkComponentManager* Manager, FGameplayTag CurrentState, FGameplayTag DesiredState) {}
virtual void CheckDefaultInitialization() {}
virtual void OnActorInitStateChanged(const FActorInitStateChangedParams& Params) {}

それ以外は、オーバーライドするのではなく呼び出します。

呼び出し効果
RegisterInitStateFeature()この実装クラスをマネージャーに登録します(OnRegister から呼び出します)。
UnregisterInitStateFeature()登録とバインド済みデリゲートを解除します(EndPlay から呼び出します)。
BindOnActorInitStateChanged(FeatureName, RequiredState, bCallIfReached)OnActorInitStateChanged をバインドし、ハンドルを ActorInitStateChangedHandle に保存します。
TryToChangeInitState(DesiredState)CanChangeInitState、HandleChangeInitState の順に実行してから、マネージャーに通知します。
ContinueInitStateChain(const TArray<FGameplayTag>& InitStateChain)現在の状態からチェーンをたどり、各ステップで CanChangeInitState と HandleChangeInitState を実行してマネージャーに通知します。到達した最も先の状態を返します。
CheckDefaultInitializationForImplementers()同じアクターのほかの各フィーチャーに対して CheckDefaultInitialization を呼び出します。
HasReachedInitState(DesiredState) / GetInitState()マネージャーを通じて、このフィーチャーの状態を確認します。

CheckDefaultInitialization のオーバーライドでは通常、CheckDefaultInitializationForImplementers() を呼び出してから、プロジェクトで定義した順序付きタグリストを指定して ContinueInitStateChain を呼び出します。コンポーネントの実装例については、references/game-feature-patterns.md を参照してください。

モジュール式コンポーネントの基底クラス

基底クラス想定する所有者型付きアクセサー
UGameFrameworkComponent任意の AActorGetGameInstance<T>()、GetGameInstanceChecked<T>()、HasAuthority()
UPawnComponentAPawnGetPawn<T>()、GetPawnChecked<T>()、GetPlayerState<T>()、GetController<T>()
UControllerComponentAControllerGetController<T>()、GetControllerChecked<T>()、GetPawn<T>()、GetViewTarget<T>()、GetPawnOrViewTarget<T>()、GetPlayerState<T>()、GetPlayer<T>()
UPlayerStateComponentAPlayerStateGetPlayerState<T>()、GetPlayerStateChecked<T>()
UGameStateComponentAGameStateBaseGetGameState<T>()、GetGameStateChecked<T>()、GetGameMode<T>()

5 つすべてが ModularGameplay にあり、#include "Components/<Name>.h" でインクルードします。UGameFrameworkComponent は UActorComponent を継承し、Blueprintable, BlueprintType です。インジェクションするコンポーネントには、生の UActorComponent よりこれらを優先してください。アクセサーは所有者の型に対して static_assert でチェックされ、初期化状態インターフェースもこれらを前提に設計されています。

プロジェクトポリシーとオブザーバー

UGameFeaturesProjectPolicies は、読み込み可能なプラグインと、各ビルドタイプで読み込むデータを決定します。プロジェクト設定でサブクラスを選択すると、次の内容が書き込まれます。

[/Script/GameFeatures.GameFeaturesSubsystemSettings]
GameFeaturesManagerClassName=/Script/MyGame.MyGameFeaturesProjectPolicies

便利な仮想関数:InitGameFeatureManager()、ShutdownGameFeatureManager()、IsPluginAllowed(const FString& PluginURL, FString* OutReason) const、GetGameFeatureLoadingMode(bool& bLoadClientData, bool& bLoadServerData) const、ShouldReadPluginDetails(const FString& PluginDescriptorFilename) const、GetPreloadBundleStateForPlugin(const FString& PluginName) const、IsLoadingStartupPlugins() const。UDefaultGameFeaturesProjectPolicies はフォールバック実装です。サブクラスのテンプレートはreferences/game-feature-patterns.mdにあります。

UGameFeaturesSubsystemSettings::LoadStateClient と ::LoadStateServer は、クライアント/サーバーのアセットフィルタリングに使用する FName バンドル状態です。この設定クラスには、EnabledPlugins、DisabledPlugins、AdditionalPluginMetadataKeys も含まれています。

1 つの機能のデータアセットに紐づかない、横断的なリアクションを実装するには、IGameFeatureStateChangeObserver を実装して登録します。

UGameFeaturesSubsystem::Get().AddObserver(MyObserver,
    UGameFeaturesSubsystem::EObserverPluginStateUpdateMode::CurrentAndFuture);

EObserverPluginStateUpdateMode は FutureOnly または CurrentAndFuture です。後者は追加時に現在のプラグイン状態を再通知するため、プラグインが多数あるプロジェクトではコストが高くなります。RemoveObserver(MyObserver) で削除します。オブザーバーのフックには、OnGameFeatureRegistering(const UGameFeatureData*, const FString& PluginName, const FString& PluginURL)、OnGameFeatureLoading(const UGameFeatureData*, const FString& PluginURL)、OnGameFeatureActivating(const UGameFeatureData*, const FString& PluginURL)、OnGameFeatureDeactivating(const UGameFeatureData*, FGameFeatureDeactivatingContext& Context, const FString& PluginURL)、およびダウンロードとマウントのフックが含まれます。データが関与する場合は、機能のデータアセットに UGameFeatureAction を使用してください。

非推奨 — 使用しないでください

使用しない5.8 で使用ソース
.uplugin 内の "Type": "GameFeature"プラグインを Plugins/GameFeatures/ の下に配置し、"ExplicitlyLoaded": true を設定しますPluginDescriptor.cs にプラグインレベルの Type キーはありません
"BuiltInAutoRegister"/"BuiltInAutoLoad"/"BuiltInAutoActivate""BuiltInInitialFeatureState"GameFeaturesSubsystem.cpp:5079-5090 のレガシーフォールバック
AddObserver(Observer)AddObserver(Observer, EObserverPluginStateUpdateMode::CurrentAndFuture)GameFeaturesSubsystem.h:488 で UE_DEPRECATED(5.7)
IsPluginAllowed(PluginURL)IsPluginAllowed(PluginURL, OutReason)GameFeaturesProjectPolicies.h:102 で UE_DEPRECATED(5.6)
GetStreamingAssetInstallBundles(PluginURL)GetStreamingAssetInstallModes(PluginURL, InstallBundleNames)GameFeaturesProjectPolicies.h:154 で UE_DEPRECATED(5.6)
FInstallBundlePluginProtocolOptions::ReleaseInstallBundleFlagsなし — リリースフラグは内部で適用されますGameFeaturesSubsystem.h:409 で UE_DEPRECATED(5.6)
FString ベースのプラグイン詳細(FPluginString)UE_GAME_FEATURE_PLUGIN_DETAILS_USE_UTF8_STRING=1 を設定し、UTF8 形式を使用しますGameFeaturesSubsystem.h:258 で UE_DEPRECATED(5.8)
引数なしの OnGameFeatureActivating() のオーバーライドOnGameFeatureActivating(FGameFeatureActivatingContext& Context) をオーバーライドしますGameFeatureAction.h:38-39 の「旧形式のアクティベーション関数」
GetGameFeaturePluginState(URL)GetPluginState(URL)エンジン関数ではありません。実際の呼び出しは GameFeaturesSubsystem.h:731 にあります
UGameFeatureData::Actions の直接操作GetActions()GameFeatureData.h:120 で Actions は保護されています。ゲッターは :102 にあります
ULyraExperienceDefinition、ULyraExperienceManagerComponent、UGameFeatureAction_AddInputContextMappingLyra のサンプルコードであり、エンジン API ではありません — 独自の同等機能を実装し、references/experience-system.md を参照してください5.8 のエンジンヘッダーにはありません

よくある間違い

プラグインの Type をでっち上げる: .uplugin にプラグインレベルの Type キーはないため、"Type": "GameFeature" は黙って無視され、プラグインはフィーチャーになりません。Plugins/GameFeatures/ の下に配置し、"ExplicitlyLoaded": true を設定してください。

レシーバーを登録し忘れる: コンポーネントは登録済みのアクターにのみ注入されます。登録し忘れても何もログに記録されません。

// WRONG — no components are ever added
void AMyCharacter::BeginPlay() { Super::BeginPlay(); }
// RIGHT
void AMyCharacter::BeginPlay()
{
    Super::BeginPlay();
    UGameFrameworkComponentManager::AddGameFrameworkComponentReceiver(this);
}

FComponentRequestHandle を破棄する: ハンドルは RAII であるため、破棄するとリクエストは直ちに削除されます。

// WRONG — the temporary destructs at the end of the statement
CompMgr->AddComponentRequest(ActorClass, UMyHealthComponent::StaticClass(), AdditionFlags);
// RIGHT — store it for the lifetime of the injection
RequestHandle = CompMgr->AddComponentRequest(ActorClass, UMyHealthComponent::StaticClass(), AdditionFlags);

コンポーネントマネージャーをエンジンサブシステムとして取得する: これは UGameInstanceSubsystem なので、GEngine->GetEngineSubsystem<UGameFrameworkComponentManager>() は null を返します。代わりに UGameFrameworkComponentManager::GetForActor(MyActor) を使用してください。

一時停止した非アクティベーションを再開しない: PauseDeactivationUntilComplete が呼び出され、返された FSimpleDelegate が実行されない場合、プラグインは永久に Deactivating のままになります。失敗時を含め、すべての経路で実行してください。

BeginPlay でコンポーネント間のセットアップを行う: 別のフィーチャーによって注入されるコンポーネントは、まだ存在しない場合があります。

// WRONG — the other component may be added later
void UMyModularComponent::BeginPlay()
{
    Super::BeginPlay();
    GetOwner()->FindComponentByClass<UMyOtherComponent>()->Configure();
}
// RIGHT — react once the shared state is reached
void UMyModularComponent::HandleChangeInitState(UGameFrameworkComponentManager* Manager, FGameplayTag CurrentState, FGameplayTag DesiredState)
{
    if (DesiredState == TAG_InitState_DataInitialized)
    {
        GetOwner()->FindComponentByClass<UMyOtherComponent>()->Configure();
    }
}

OnGameFeatureActivating の両方のオーバーロードをオーバーライドする: 基底クラスのコンテキスト版は引数なし版を呼び出すため、アクティベーションコードが 2 回実行されます。コンテキスト版のみをオーバーライドしてください。

Lyra クラスをエンジン API とみなす: ULyraExperienceDefinition、ULyraExperienceManagerComponent、および Lyra 独自のアクションサブクラスは Lyra サンプルに含まれ、エンジンにはありません。エンジン側の要素は UGameFeatureData、UGameFeatureAction、UGameFrameworkComponentManager です。

関連スキル

  • ue-gameplay-tags-messaging — 初期状態、タグコンテナ、クエリとして使用する FGameplayTag の値の宣言
  • ue-module-build-system — プラグインとモジュールの構成、Build.cs の依存関係、読み込みフェーズ
  • ue-actor-component-architecture — コンポーネントの作成、登録、アタッチ、ティック
  • ue-gameplay-abilities — フィーチャーのコンポーネントからアビリティと属性セットを付与する方法
  • ue-data-assets-tables — プライマリデータアセット、Asset Manager のスキャン、アセットバンドル
  • ue-input-system — フィーチャーが追加および削除する Enhanced Input マッピングコンテキスト
  • ue-gameplay-framework — GameMode、GameState、PlayerController、PlayerState のライフサイクル
  • ue-world-level-streaming — フィーチャーが追加する World Partition のコンテンツバンドルとデータレイヤー

コメント