StructOpsTypeTraits メモ

UnrealEngine

初めに

※確認UEバージョン:5.0.3

USTRUCTの型特性を設定できるStructOpsTypeTraits で設定できるフラグについてメモしていきます。

フラグは下のようにUSTRUCT構造体宣言後、TStructOpsTypeTraitsを追加してください。

USTRUCT()
struct FMyStruct {
	GENERATED_BODY()
	
};

template<>
struct TStructOpsTypeTraits<FMyStruct> : public TStructOpsTypeTraitsBase2<FMyStruct>
{
	enum
	{
		// ここでフラグを設定していきます。
		// 例:		
    // WithAddStructReferencedObjects = true,
	};
};

TStructOpsTypeTraitsの型特性が適用されるのは、UPROPERTYがついているメンバ変数のみです。

UE機能側に型特性を伝えるためのテンプレート構造体なので、関数内処理でローカル変数として構造体を作成しても、型特性は適用されません。

※UScriptStruct経由で構造体を変更する場合は型特性が適用されます。

WithZeroConstructor

プロパティ書き込み時(ロード時)に構造体全体を0で埋めます。(MemZero)

このフラグを有効にした場合は、コンストラクタ呼び出しがありません。

プロパティ書き込み前(ロード前)に発生するコンストラクタ(構造体を持っているUObjectクラス生成時のコンストラクタ)は通常通り呼ばれます。

WithNoInitConstructor

プロパティ書き込み時(ロード時)にデフォルトコンストラクタではなく、独自に定義したEForceInitをパラメータにもつコンストラクタが呼ばれます。

このフラグを有効にした場合は、以下のようなEForceInitをパラメータにもつコンストラクタを追加する必要があります。

explicit FORCEINLINE FMyStruct(EForceInit);

WithNoDestructor

プロパティ書き込み前(ロード前)にデストラクタを呼びません。(処理速度向上が見込めます。)

また、FMemoryで生成したポインタの構造体を開放する前にUScriptStruct経由でデストラクタを呼び出す際にもフラグ設定が使用されます。(FMemory::Freeはvoid*を引数にしており、freeの際にデストラクタが呼ばれないためUScriptStruct経由で呼んでいるようです。)

参考:UDataTable::RemoveRow

WithCopy

構造体のコピーを可能にします。

デフォルトでは、TIsPODTypeがfalseの場合のみコピー可能になっています。

WithIdenticalViaEquality

同型構造体を比較する際に独自に定義したoperator==関数が使用されます。

このフラグを有効にした場合は、以下のようなoperator==関数を追加する必要があります。

bool operator==(const FMyStruct& Other) const;

WithIdenticalと同時にtrueにすることはできません。

WithIdentical

同型構造体を比較する際に独自に定義したIdentical関数が使用されます。

このフラグを有効にした場合は、以下のようなIdentical関数を追加する必要があります。

bool Identical(const FMyStruct* Other, uint32 PortFlags) const;

WithIdenticalViaEqualityと同時にtrueにすることはできません。

WithExportTextItem

構造体を文字列にシリアル化する際に独自に定義したExportTextItem関数が使用されます。

シリアル化した文字列は、UE上で構造体パラメータをコピーする際などで使用されています。

このフラグを有効にした場合は、以下のようなExportTextItem関数を追加する必要があります。

bool ExportTextItem(FString& ValueStr, FMyStruct const& DefaultValue, class UObject* Parent, int32 PortFlags, class UObject* ExportRootScope) const;

WithExportTextItemとWithImportTextItemはセットで使用するのが一般的です。

WithImportTextItem

構造体をシリアル化された文字列から生成する際に、独自に定義したImportTextItem関数が使用されます。

入力される文字列は、ExportTextItem関数などから出力されたシリアル化文字列が使用されます。

このフラグを有効にした場合は、以下のようなImportTextItem関数を追加する必要があります。

bool ImportTextItem(const TCHAR*& Buffer, int32 PortFlags, UObject* Parent, FOutputDevice* ErrorText, FArchive* InSerializingArchive = nullptr);

WithExportTextItemとWithImportTextItemはセットで使用するのが一般的です。

WithAddStructReferencedObjects

構造体はガベージコレクターへの参照を追加できる、独自に定義したAddStructReferencedObjects 関数を使用します。

このフラグを有効にした場合は、以下のようなAddStructReferencedObjects 関数を追加する必要があります。

void AddStructReferencedObjects(class FReferenceCollector& Collector);

構造体でUPROPERTYを付けられないメンバのGC解放を防ぐためによく使用されます。

AddReferencedObjects関数はUObjectクラスの

void UObject::AddReferencedObjects(UObject* This, FReferenceCollector& Collector)

と類似の関数になります。

WithSerializer

構造体は、その状態を FArchive にシリアル化するための、独自に定義したSerialize関数があり、シリアライズ化で呼び出します。

このフラグを有効にした場合は、以下のようなSerialize関数を追加する必要があります。

bool Serialize(FArchive& Ar);

Serialize(FArchive& Ar)関数はUObjectクラスの

void UObject::Serialize(FArchive& Ar)

と類似の関数になります。

WithStructuredSerializer

構造体は、その状態を FStructuredArchiveにシリアル化するための、独自に定義したSerialize関数があり、シリアライズ化で呼び出します。

このフラグを有効にした場合は、以下のようなSerialize関数を追加する必要があります。

bool Serialize(FStructuredArchive::FSlot Slot);

Serialize(FStructuredArchive::FSlot Slot)関数はUObjectクラスの

void UObject::Serialize(FStructuredArchive::FRecord Record)

と類似の関数になります。

WithPostSerialize

構造体は、独自に定義したPostSerialize関数がありシリアライズ後に呼び出します。

このフラグを有効にした場合は、以下のようなPostSerialize 関数を追加する必要があります。

void PostSerialize(const FArchive& Ar);

WithNetSerializer

構造体は独自に定義したNetSerialize 関数があり、ネットワークレプリケーション時にシリアル化する目的で呼び出します。(ネットワークに送るデータを減らす等、最適化ができます。)

このフラグを有効にした場合は、以下のようなNetSerialize 関数を追加する必要があります。

bool NetSerialize(FArchive& Ar, class UPackageMap* Map, bool& bOutSuccess);

WithNetDeltaSerializer

構造体は独自に定義したNetDeltaSerialize関数があり、前回ネットシリアライズした際の状態の違いのみをシリアル化する目的で呼び出します。

このフラグを有効にした場合は、以下のようなNetDeltaSerialize関数を追加する必要があります。

	bool NetDeltaSerialize(FNetDeltaSerializeInfo& DeltaParams);

WithSerializeFromMismatchedTag

構造体は独自に定義したFArchiveを引数にもつ SerializeFromMismatchedTag 関数があり、同名プロパティなのに型が異なる場合等にデータを変換する目的で呼ばれます。

このフラグを有効にした場合は、以下のようなSerializeFromMismatchedTag関数を追加する必要があります。

bool SerializeFromMismatchedTag(struct FPropertyTag const& Tag, FArchive& Ar);

WithStructuredSerializeFromMismatchedTag

構造体は独自に定義したFStructuredArchiveを引数にもつ SerializeFromMismatchedTag 関数があり、同名プロパティなのに型が異なる場合等にデータを変換する目的で呼ばれます。

このフラグを有効にした場合は、以下のようなSerializeFromMismatchedTag関数を追加する必要があります。

	bool SerializeFromMismatchedTag(const FPropertyTag& Tag, FStructuredArchive::FSlot Slot);

WithPostScriptConstruct

構造体は独自に定義したPostScriptConstruct関数があり、ブループリントで構造体構築後に呼び出されます。

このフラグを有効にした場合は、以下のようなPostScriptConstruct関数を追加する必要があります。

void PostScriptConstruct();

WithNetSharedSerialization

構造体を所持しているUObjectインスタンスがパッケージとしてマッピングされていなくてもネットシリアライズ化が可能なことを示すフラグです。

このフラグは WithNetSerializer と一緒にtrueにしないと意味がないフラグになります。

WithGetPreloadDependencies

構造体は独自に定義した GetPreloadDependencies 関数があり、構造体型のパラメータを生成する前にロードしておかなければならないUObjectをロードする際に呼び出されます。

このフラグを有効にした場合は、以下のようなGetPreloadDependencies 関数を追加する必要があります。

	void GetPreloadDependencies(TArray<UObject*>& OutDeps);

WithPureVirtual

構造体には純粋仮想関数があり、純粋仮想関数にはPURE_VIRTUALマクロが設定されています。

このフラグを有効にした場合は、純粋仮想関数とそれに対応したPURE_VIRTUALマクロを追加する必要があります。

PURE_VIRTUALマクロ
宣言箇所 CoreMiscDefines.h (60行目)
第1引数:関数名
第2引数:デフォルトreturn文

PURE_VIRTUALマクロの使用例を紹介します。

struct FMyObject{
virtual int Add(int InNum) PURE_VIRTUAL(FMyObject::Add, return 0; );
virtual bool IsZero() PURE_VIRTUAL(FMyObject::IsZero, return false; );
virtual void ZeroClear()PURE_VIRTUAL(FMyObject::ZeroClear,);
};

純粋仮想関数を持つ構造体は通常継承されずに実体をもつことができないのですが、PURE_VIRTUALマクロを使用することで、(内部的に関数が定義され)コンパイルが通るようになります。

WithPureVirtualがある理由としては、ビルドパラメータで純粋仮想関数チェックを行うようにすることができ、チェック有効時 & WithPureVirtualがtrueの場合は、構造体の生成を停止するようにしているようです。

まとめ

フラグ名trueの場合
WithZeroConstructorパラメータ生成時に構造体全体を0で埋めます。
WithNoInitConstructorパラメータ生成時にEForceInitをパラメータにもつコンストラクタを呼びます。
WithNoDestructorパラメータ破棄の際に、デストラクタを呼びません。
WithCopy構造体のコピーを可能にします。
WithIdenticalViaEquality※WithIdenticalと同時にtrueにできません。
構造体はoperator==関数を介して比較できます。
WithIdentical※WithIdenticalViaEqualityと同時にtrueにできません。
構造体はIdentical関数を介して比較できます。
WithExportTextItemExportTextItem関数を介して構造体パラメータを文字列として出力します。
WithImportTextItemImportTextItem関数を介して構造体パラメータを文字列から生成します。
WithAddStructReferencedObjectsAddStructReferencedObjectsを介してGCで回収されたくないオブジェクトを追加できます。
WithSerializerSerialize関数で構造体をシリアライズします。
WithStructuredSerializerSerialize関数で構造体をシリアライズします。
WithPostSerializeシリアライズ化後にPostSerialize関数を呼び出します。
WithNetSerializerネットワークレプリケーション時にNetSerialize関数でシリアライズ化します。
WithNetDeltaSerializer前回NetSerialize操作を行ったときとのデータ差分をシリアライズ化するNetDeltaSerialize 関数を呼び出します。
WithSerializeFromMismatchedTagSerializeFromMismatchedTag関数で他の構造体タイプから変換する処理を呼び出せます。
WithStructuredSerializeFromMismatchedTagSerializeFromMismatchedTag関数で他の構造体タイプから変換する処理を呼び出せます。
WithPostScriptConstructBP側で構造体が構築された後、PostScriptConstruct関数を呼び出します。
WithNetSharedSerialization構造体には、状態をシリアライズ化するためにパッケージ マップを必要としない NetSerialize 関数があります。
WithGetPreloadDependencies構造体生成前にロードする必要があるオブジェクトを取得できるGetPreloadDependencies関数があります。
WithPureVirtual構造体には純粋仮想関数があり、PURE_VIRTUALマクロを使用しています。
タイトルとURLをコピーしました