PaperSloth’s diary

主にゲーム開発関連についての記事を書きます。

UE4 Unreal C++でデストラクタ

環境

UE4.19.0
Visual Studio 2015 Community


参考文献

下記ドキュメントはUE4を触っている人は必ず目を通しておくべきだと思います。
今回はこのドキュメントを参考にActorの解放処理についてみていきます。
Unreal Engine | アクタのライフサイクル


UE4でのデストラクタ

結論から書くとデストラクタはUObjectを継承したクラスでは基本的に使用しません。

class PROJECTNAME_API AExampleActor : public AActor
{
	GENERATED_BODY()
public:	
	AExampleActor();
	// 下記はNG
	virtual ~AEampleActor();	

UObjectを継承したクラスではBeginDestroyをOverrideすると良さそうです。
これはオブジェクトがGC用にマークされた状態でも、まだ削除されていないときに呼び出されるものです。
ゲームプレイ機能は後述のEndPlayで解放し、BeginDestroyでオブジェクトが使用していた全リソースを解放します。

// header側
class PROJECTNAME_API AExampleActor : public AActor
{
	GENERATED_BODY()
public:	
	AExampleActor();
	virtual void BeginDestroy() override;
}

// cpp側
void AExampleActor::BeginDestroy()
{
	Super::BeginDestroy();
}


AActorを継承したクラスで明示的なDestroy呼び出し等による終了処理を記述したい場合にはEndPlayを使用します。

// header側
class PROJECTNAME_API AExampleActor : public AActor
{
	GENERATED_BODY()
public:	
	AExampleActor();
	virtual void EndPlay(const EEndPlayReason::Type EndPlayReason);
}

// cpp側
void AExampleActor::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
	Super::EndPlay(EndPlayReason);
}


他にも終了処理の過程にはDestroy関数やOnDestroyのようなデリゲートもありますが
ドキュメントを見た限りでは特別な理由がなければ終了処理はEndPlayで良さそうです。

また、ReceiveEndPlayなどのReceive~系はC++側の処理が呼ばれる際に合わせて呼び出されるBlueprint側の処理になります。
Blueprint側のEndPlay等は実際にはReceiveEndPlayを使用しています。


まとめ

終了処理を明示的に記述したい場合はEndPlay
デストラクタの代替機能が欲しい場合はBeginDestroy

UObjectを継承したクラスでは基本的にデストラクタを記述する必要はありません。


また、今回は解説しませんがUnreal C++でもどうしてもC++のnewを使いたいことがあるかもしれません。
そういった特殊なケースの場合はRuntime/Core/Public/HALUnrealMemory.hに目を通しておくと幸せになれるかもしれません。
mallocやfree等々メモリーに関する処理が幾つか用意されています。