プログラミング サブシステム

Unreal Engine 4 のプログラミング サブシステムの概要です。

Windows
MacOS
Linux

Unreal Engine 4 (UE4) のサブシステムは、管理されたライフタイムを持つ自動的にインスタンス化されたクラスです。このクラスを利用すると、拡張ポイントを簡単に使用できるため、プログラマはエンジン クラスの変更または上書きするといった複雑な作業を回避しつつ、ブループリントや Python を公開できます。

現在サポートされているサブシステムのライフタイムは以下です。

サブシステム

継承元

Engine

UEngineSubsystem クラス

Editor

UEditorSubsystem クラス

GameInstance

UGameInstanceSubsystem クラス

LocalPlayer

ULocalPlayerSubsystem クラス

例えば、次の基本クラスから派生するクラスを作成する場合、

class UMyGamesSubsystem : public UGameInstanceSubsystem

結果は次のようになります。

  1. UGameInstance が作成された後、UMyGamesSubsystem というインスタンスも作成されます。

  2. UGameInstance が初期化されるとき、サブシステムで Initialize() が呼び出されます。

  3. UGameInstance が終了するとき、サブシステムで Deinitialize() が呼び出されます。

  4. この時点で、サブシステムへの参照は削除されます。サブシステムへの参照がなくなると、サブシステムはガベージ コレクションされます。

サブシステムを使用する理由

プログラミング サブシステムを使用する理由は、以下をはじめ、いくつかあります。

  • プログラミング時間が短縮される。

  • エンジン クラスのオーバーライド回避に役立つ。

  • ただでさえ入り組んだクラスにさらに API を追加しなくてすむ。

  • ユーザー フレンドリなタイプのノードを通じてブループリントにアクセスできる。

  • エディタ スクリプティングやテスト コードの記述のために Python スクリプトにアクセスできる。

  • コードベースのモジュール性と一貫性を実現する。

サブシステムは、プラグインを作成する際に特に役立ちます。プラグインを機能させるのに必要なコードに関する指示を用意する必要がないからです。ユーザーはプラグインをゲームに追加するだけでよく、デベロッパーはプラグインがインスタンス化され、初期化されるタイミングが正確にわかります。その結果、デベロッパーは API と UE4 で提供されている機能の使用方法に注力できます。

ブループリントでサブシステムにアクセスする

サブシステムは、コンテキストを理解し、キャストを必要としないスマート ノードによって、自動的にブループリントに公開されます。標準の UFUNCTION() マークアップとルールを使用して、ブループリントで使用可能な API を管理しています。

ブループリント グラフで右クリックしてコンテキスト メニューを表示し、「subsystems」を検索すると、以下の画像のような表示になります。主要なタイプそれぞれにカテゴリがあり、具体的なサブシステムそれぞれに個別のエントリがあります。
Subsystems_01.png

上記からノードを追加すると、次のような結果が得られます。
Subsystems_02.png

Python でサブシステムにアクセスする

Python を使用している場合、ビルトインのアクセサーを使用して、以下の例のようにサブシステムにアクセスできます。

my_engine_subsystem = unreal.get_engine_subsystem(unreal.MyEngineSubsystem)
my_editor_subsystem = unreal.get_editor_subsystem(unreal.MyEditorSubsystem)

Python は現在実験的な機能です。

サブシステムのライフタイムの詳細

Engine サブシステム

class UMyEngineSubsystem : public UEngineSubsystem { ... };

Engine サブシステムのモジュールがロードされると、サブシステムはモジュールの Startup() 関数から戻った後に Initialize() を実行します。

また、モジュールの Shutdown() 関数から戻った後に Deinitialize() を実行します。

UMyEngineSubsystem MySubsystem = GEngine->GetEngineSubsystem<UMyEngineSubsystem>();

Editor サブシステム

class UMyEditorSubsystem : public UEditorSubsystem { ... };

Editor サブシステムのモジュールがロードされると、サブシステムはモジュールの Startup() 関数から戻った後に Initialize() を実行します。

また、モジュールの Shutdown() 関数から戻った後に Deinitialize() を実行します。

UMyEditorSubsystem MySubsystem = GEditor->GetEditorSubsystem<UMyEditorSubsystem>();

GameInstance Subsystems

class UMyGameSubsystem : public UGameInstanceSubsystem { ... };

これらのサブシステムは、以下のように UGameInstance を通してアクセスされます。

UGameInstance* GameInstance = ...;
UMyGameSubsystem* MySubsystem = GameInstance->GetSubsystem<UMyGameSubsystem>();

LocalPlayer サブシステム

class UMyPlayerSubsystem : public ULocalPlayerSubsystem { ... };

これらのサブシステムは、以下のように ULocalPlayer を通してアクセスされます。

ULocalPlayer* LocalPlayer = ...;
UMyPlayerSubsystem * MySubsystem = LocalPlayer->GetSubsystem<UMyPlayerSubsystem>();

サブシステムの例

次の例では、収集したリソースの数を追跡する統計システムをゲームに追加します。

UGameInstance から派生させて UMyGamesGameInstance を作成した後、それに IncrementResourceStat() 関数を追加します。しかし、ゆくゆくは他の統計や、統計の集計、統計の保存/読み込み機能などを追加した方が良いでしょう。そのため、UMyGamesStatsSubsystem など、1 つのクラスにそのすべてを配置することにします。

再び UMyGamesGameInstance を作成して、UMyGamesStatsSubsystem 型のメンバーを追加します。その後、そこにアクセサーを追加して、Initialize 関数と Deinitialize 関数をフックします。しかし、これにはいくつかの問題があります。

  • UGameInstance のゲーム固有の派生物がない。

  • UMyGamesGameInstance は存在するが、既に大量の関数があり、そこにさらに追加するのは最適性に欠ける。

十分に複雑なゲームで UGameInstance から派生させるのが妥当な理由は多数あります。しかし、サブシステムがある場合、それを使う必要はありません。なんと言っても、サブシステムを使用すると、他の方法よりも必要なコーディングが少なくなります。

そのため、最終的に使用するコードを以下の例に示します。

UCLASS()
class UMyGamesStatsSubsystem : public UGameInstanceSubsystem
{
    GENERATED_BODY()
public:
    // Begin USubsystem (開始)
    virtual void Initialize(FSubsystemCollectionBase& Collection) override;
    virtual void Deinitialize() override;
    // End USubsystem (終了)

    void IncrementResourceStat();
private:
    // All my variables (すべての変数)
};
Tags
Select Skin
Light
Dark

Welcome to the new Unreal Engine 4 Documentation site!

We're working on lots of new features including a feedback system so you can tell us how we are doing. It's not quite ready for use in the wild yet, so head over to the Documentation Feedback forum to tell us about this page or call out any issues you are encountering in the meantime.

We'll be sure to let you know when the new system is up and running.

Post Feedback