C++ ときどき ごはん、わりとてぃーぶれいく☆

USAGI.NETWORKのなかのひとのブログ。主にC++。

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::RemoveFromRootUObjectBaseUtility::AddToRootUObjectBaseUtility::SetFlags( RF_MarkAsRootSet ) と等しい。RF_MarkAsRootSetEObjectFlags で定義される enum 値。

References