UE4/C++: C++er がUE4型のシングルトンを作る際に気をつける事
「UE4 にはガベージコレクションがある。しかし特に C++er は正しい実装を過剰に気に掛ける必要がある。」
UE4Editor から GUI でも設定できる GameSingletonClass
, GameInstance
を使う場合は気にする必要は無い。今回はその仕組みを使わない場合の話。
UObject
派生型のシングルトン・オブジェクトを C++ の実装側だけで NewObject
し意図しないガベージコレクションを行わせない方法:
// static なシングルトンのインスタンスを取得するメンバー関数など UMySingletonType* GetInstance() { if ( instance = nullptr ) { instance = NewObject< UMySingletonType >(); check( instance ) // ↓ これ: UObject の基底型の UObjectBaseUtility のメンバー関数 instance->AddToRoot(); } return instance; }
たまに忘れる。そして初回動作に安心してしばらく、1分以上経過してからインスタンスが事故を起こす。この時、直接インスタンスを自身のコードで扱っていればすぐに気づくが、このクラスを介して保持しているはずオブジェクトをクローズドソースのサードパーティー製のライブラリーに弱参照させている場合など原因へ辿り着くには時間と経験が必要になり困難なバグとなる。
なお、 UObjectBaseUtility::AddToRoot
の対は UObjectBaseUtility::RemoveFromRoot
。UObjectBaseUtility::AddToRoot
は UObjectBaseUtility::SetFlags( RF_MarkAsRootSet )
と等しい。RF_MarkAsRootSet
は EObjectFlags
で定義される enum
値。