UObject


概要

Unreal Engineにおけるオブジェクトの基本となるクラス。 ゲームプレイ中に使用される多くの要素は、この「UObject」に基づいて構築されている。

インスタンス生成

インスタンス生成には、基本的にエンジンが提供している以下の関数を使用する。

CreateDefaultSubobject

「UObject」やその派生クラスのコンストラクタ内でインスタンスを生成する場合に用いる。
「UObject」にある「CreateDefaultSubobject」関数は、内部的に「ObjectInitializer」を取得してその中の同名関数を実行している。
また、「Subobject」は「あるUObjectから所有(Outerとして指定)される別のUObjectのこと」を指す。 これは、主に構成部品として機能することを意味し、コンポーネントなどが該当する。

NewObject

コンストラクタ以外でインスタンスを生成する場合に用いる。
「NewObject」関数は、「UObjectGlobals.h」で定義されているグローバル関数である。

メモリ管理

メモリ管理は、ガーベジコレクション(GC)と呼ばれる仕組みによって自動的に制御されている。 これは、C++における明示的なメモリ解放を不要とし、使用されなくなったオブジェクトを自動的に破棄する仕組みである。 すべての「UObject」インスタンスは、「GUObjectArray」グローバル配列に登録されており、「GC」はそこから現在の生存状態を把握している。

RootSetを起点とした参照追跡

「GC」は、ある「UObject」が現在も使用中であるかどうかを、特定の起点からの強参照関係によって判断する。 この起点となるのが「RootSet」であり、「AddToRoot」関数によって明示的に登録されたオブジェクトで構成される。 「UWorld」や「GameInstance」といった重要なオブジェクトは、エンジン内部でこのルートセットに含まれるよう管理されている。 「RootSet」から強参照を辿っても到達できないオブジェクトは、使用されていないと判断され「GC」によって自動的に破棄される。

UPROPERTYで示す強参照関係

「GC」が強参照関係を正しく把握するには、参照する側のポインタにも明示的な指定が必要である。 具体的には、「UObject」へのポインタを「UPROPERTY」マクロ付きで宣言する。 そうすることで、「GC」はその参照を認識し、管理対象として追跡できるようになる。 また、「GC」によってオブジェクトが破棄されると、その参照元の「UPROPERTY」ポインタは自動的に「nullptr」に初期化される。 この仕組みによって、ダングリングポインタの発生を防ぐことができる。

TWeakObjectPtrで示す弱参照関係

参照先の「UObject」に対して強参照を持ちたくない場合、つまりそのオブジェクトの寿命に影響を与えず 有効なときだけアクセスしたい場合には、「TWeakObjectPtr」を使用する。 「Get」や「IsValid」関数は、引数に特別な指定をしない限り、「GUObjectArray」を通じて参照先の有効性を確認する。 参照先がすでに無効な状態であれば、「Get」関数は「nullptr」を、「IsValid」関数は「false」を返すため、安全なアクセスが可能となる。

MarkAsGarbageでの明示的破棄

「UObject」を明示的に破棄するには、基本的にその型ごとに用意された専用の関数を使用する。 例えば、「AActor」には「Destroy」関数、「UActorComponent」には「DestroyComponent」関数があり これらは内部で「MarkAsGarbage」関数を呼び出して、オブジェクトを破棄対象としてマークしている。 専用関数がない場合は、「MarkAsGarbage」関数を直接使用してもよい。

IsValidによる有効性判定

破棄対象としてマークされたオブジェクトは、次回の「GC」実行時に削除されるが、それまでは一時的にメモリ上に残ることがある。 この期間中、オブジェクトは一見有効に見えても、すでに無効と見なされており安全に使用することはできない。 「UObject」ポインタを扱う際は、破棄対象のものを参照していないかを確認するため、「IsValid」関数による判定を行うのが良い。 「IsValid」関数は、ポインタが「nullptr」でないことに加え、破棄対象でないことを判定してくれる。