Ue4

UE4マクロ定義の深い理解-GENERATED_BODY



Deep Understanding Ue4 Macro Definition Generated_body




この記事はcartzhangによって書かれました。転載する際に出典を示してください。全著作権所有。
記事のリンク: http://blog.csdn.net/cartzhang/article/details/72834164
OF:cartzhang

1. GENERATED_BODYは何を達成しましたか?


過去数年間にエンジンコードを書くとき、それはこれらのマクロ定義を使用する方法に似ており、使用法は比較的複雑です。次に、UE4を借りてレビューと分析を行います。

ベータ版:4.15
例を参照してください。



// Fill out your copyright notice in the Description page of Project Settings.

民間
TClass&演算子=(TClass &&)代入関数
TClass&演算子=(constTClass&)const割り当て
TRequiredAPI静的UClass * GetPrivateStaticClass(constTCHAR *パッケージ)
公衆
/ *に関連する#EClassFlagsのビット単位の和集合この クラス /
列挙型{StaticClassFlags = TStaticFlags}
/ *基本クラスのTypedef({{typedef-type}}) /
typedef TSuperClass Super
/ * {{typedef-type}}のTypedef。 /
typedef TClass ThisClass
/ *実行時にこのクラスを表すUClassオブジェクトを返します /
列をなして静的UClass * StaticClass()
//静的関数はGetPrivateStaticClassを使用します
{
戻るGetPrivateStaticClass(TPackage)
}
/ *このクラスのStaticClassFlagsを返します /
列をなして静的EClassCastFlags StaticClassCastFlags()
{
戻るTStaticCastFlags
}
非推奨(4.7「演算子newはUObjectsで非推奨になりました。代わりにNewObjectまたはNewNamedObjectを使用してください」
列をなしてボイド*演算子新着((constsize_t InSize、UObject * InOuter =(UObject *)GetTransientPackage()、FName InName = NAME_None、EObjectFlags InSetFlags = RF_NoFlags)
{
戻るStaticAllocateObject(StaticClass()、InOuter、InName、InSetFlags)
}
/ *内部使用の場合は、StaticConstructObject()を使用して新しいオブジェクトを作成するだけです。 /
列をなしてボイド*演算子新着((constsize_t InSize、EInternal InInternalOnly、UObject * InOuter =(UObject *)GetTransientPackage()、FName InName = NAME_None、EObjectFlags InSetFlags = RF_NoFlags)
{
戻るStaticAllocateObject(StaticClass()、InOuter、InName、InSetFlags)
}
/ *内部使用の場合は、StaticConstructObject()を使用して新しいオブジェクトを作成するだけです。 /
列をなしてボイド*演算子新着((constsize_t InSize、EInternal * InMem)
{
戻る((ボイド*)InMem
}

  • 1
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 十一
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 2. 3
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 3. 4
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42


主に静的関数を実装して、NewのUClassオーバーロードを取得します。



第四に、登録プロセス


質問がありますが、上記のクラスの登録プロセスはどのように登録されますか?

StaticRegisterNativesUCollidingPawnMovementComponentとZ_Construct_UClass_UCollidingPawnMovementComponent、これらはコードでどのように使用されていますか?

タイプがわかりますか?これは実際にはUClassタイプであり、これは彼がUClassのフレンド関数であることを意味します。
UClassはClass.hにありますが、この呼び出しは.cppに実装されています。

特にClass.cppの4332行目では、これは別のマクロ定義です。

IMPLEMENT_CORE_INTRINSIC_CLASS(UClass, UStruct, { Class->ClassAddReferencedObjects = &UClass::AddReferencedObjects Class->EmitObjectReference(STRUCT_OFFSET(UClass, ClassDefaultObject), TEXT('ClassDefaultObject')) Class->EmitObjectReference(STRUCT_OFFSET(UClass, ClassWithin), TEXT('ClassWithin')) Class->EmitObjectReference(STRUCT_OFFSET(UClass, ClassGeneratedBy), TEXT('ClassGeneratedBy')) Class->EmitObjectArrayReference(STRUCT_OFFSET(UClass, NetFields), TEXT('NetFields')) } )


コアはここにあります:

// Used for intrinsics, this sets up the boiler plate, plus an initialization singleton, which can create properties and GC tokens #define IMPLEMENT_INTRINSIC_CLASS(TClass, TRequiredAPI, TSuperClass, TSuperRequiredAPI, InitCode) IMPLEMENT_CLASS(TClass, 0) // Look here, look here. TRequiredAPI UClass* Z_Construct_UClass_##TClass() UClass* Z_Construct_UClass_##TClass() { static UClass* Class = NULL if (!Class) { extern TSuperRequiredAPI UClass* Z_Construct_UClass_##TSuperClass() UClass* SuperClass = Z_Construct_UClass_##TSuperClass() Class = TClass::StaticClass() UObjectForceRegistration(Class) check(Class->GetSuperClass() == SuperClass) InitCode Class->StaticLink() } check(Class->GetClass()) return Class } static FCompiledInDefer Z_CompiledInDefer_UClass_##TClass(Z_Construct_UClass_##TClass, &TClass::StaticClass, TEXT(#TClass), false)


静的シングルトンを初期化してクラスを登録します。このコードはバージョン4.7と比較されます。まったく同じで、変更は加えられていませんが、ファイル名が変更されています。

このZ_Construct_UClass_ ## TClass()は少しおなじみですか?ちなみに、ここではフレンド関数の関数本体を実装し、UObjectCompiledInDeferで登録を実装しています。
Class = TClass :: StaticClass()は、ObjectMacros.hの1331行です。



inline static UClass* StaticClass() { return GetPrivateStaticClass(TPackage) }


また、GetPrivateStaticClassは、ObjectMacros.hの1512行目のIMPLEMENT_CLASSに関数本体を実装します。


上記のIMPLEMENT_CLASS(TClass、0)を参照してください// //ここを見て、ここを見てください。
完璧です。
答えはここにあります。このマクロ定義は、最初に登録クラスを実装します。 4番目のパラメーターStaticRegisterNatives ## TClassは、StaticRegisterNativesUCollidingPawnMovementComponent関数を今すぐ呼び出すことができるコールバック関数です。

5番目、UE4の以前の4.7バージョンと比較して


私の印象では、以前のUE4バージョンでは、GENERATED_BODYが分離されており、GENERATED_UCLASS_BODY、GENERATED_USTRUCT_BODYなどがあります。
前のプロジェクトを再度開くと、実際にコードマクロの定義が大幅に変更されています。

以前のバージョンのマクロ定義の書き込み呼び出しは現在よりも単純で、書き込み方法は同じです。つまり、現在の書き込みとは異なり、呼び出しプロセスを使用して複数のマクロを実装し、外部または外部の見栄えを良くします。コードと作業はすべて最下層の内部で処理されます。

これは、困難を内部に残し、優雅さとシンプルさを与えるためです!

これらの手順がよく知られていない場合は、バージョン4.7以前を参照することをお勧めします。

UE4の巨大なマクロ定義とシステムの高度な複雑さのために、私はコードファイル名と行数を使用して呼び出しプロセスを説明しようとしています。
あらゆる種類の切り替え、エンジンを自分で確認する必要があります。全体的なアイデアを注意深く確認する必要があります。かなり明確である必要があります。

そうは言っても、EPICは世界中の優秀なプログラマーを統合して、100年前の人工エンジンに取り組んでいます。あなたはそれを1時間で完全に理解することができます、そして私は神に私を飛ばしてくれるように頼みます! !

六、絵を描く、一緒に見ることができます。

画像

7.リファレンス

【1】 https://docs.unrealengine.com/latest/INT/Programming/Tutorials/Components/3/index.html

【二】 http://blog.csdn.net/cartzhang/article/details/22726167


最後まで待つのはとても疲れます。書き終えましたが、心配でした!

ご不明な点がございましたら、お気軽にお問い合わせください! !

閲覧していただきありがとうございます、いいねへようこそ !!