当前位置: 首页 > news >正文

网站建设行业解决方案做国内电影网站赚钱不

网站建设行业解决方案,做国内电影网站赚钱不,学生怎么做网站,圣玺企业网站建设序 最近看了看反射相关的知识#xff0c;用不说一点人话的方式来说#xff0c;反射是程序在运行中能够动态获取修改或调用自身属性的东西。 一开始我是觉得反射用处好像不大#xff0c;后续查了下一些反射的使用环境#xff0c;发现我格局小了#xff0c;我觉得用处不大的…序 最近看了看反射相关的知识用不说一点人话的方式来说反射是程序在运行中能够动态获取修改或调用自身属性的东西。 一开始我是觉得反射用处好像不大后续查了下一些反射的使用环境发现我格局小了我觉得用处不大的原因是我从c的角度来考虑使用反射在c中确实用处不大但是捏把格局打开要从更上一层的视角来看反射不要局限于c比如我们要使用c以外的东西调用c比如配置文件蓝图pythonlua这些去调c或是设计到编辑器功能的时候这时候反射就是极为好用方便的一个特性。 三种反射实现的方式 反射实现的本质其实就是想办法在运行时拿到类的数据这个数据可以手动生成也可以利用编译器的信息在c中反射大概有三种实现方式 1.利用c手动写反射结构的代码可以利用宏之类的其实就是方式3的简化版实现简单相对简单但是对使用者这来说毕竟麻烦因为如果要添加一个新的成员或函数就要手动添加一次。 2.利用c编译出来的符号表缺点每个编译器的实现不一定一样换一个编译器可能就不好使了 3.利用工具生成c代码实现反射唯一缺点是实现起来比较有难度但是使用起来简单也不会有第二种方法的缺点 在ue中使用的就是第三种办法所以ue实现了UHT这个工具。 UE5中反射系统注册信息的过程 #mermaid-svg-mvLxxSJ3s79roEa9 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-mvLxxSJ3s79roEa9 .error-icon{fill:#552222;}#mermaid-svg-mvLxxSJ3s79roEa9 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-mvLxxSJ3s79roEa9 .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-mvLxxSJ3s79roEa9 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-mvLxxSJ3s79roEa9 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-mvLxxSJ3s79roEa9 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-mvLxxSJ3s79roEa9 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-mvLxxSJ3s79roEa9 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-mvLxxSJ3s79roEa9 .marker.cross{stroke:#333333;}#mermaid-svg-mvLxxSJ3s79roEa9 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-mvLxxSJ3s79roEa9 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-mvLxxSJ3s79roEa9 .cluster-label text{fill:#333;}#mermaid-svg-mvLxxSJ3s79roEa9 .cluster-label span{color:#333;}#mermaid-svg-mvLxxSJ3s79roEa9 .label text,#mermaid-svg-mvLxxSJ3s79roEa9 span{fill:#333;color:#333;}#mermaid-svg-mvLxxSJ3s79roEa9 .node rect,#mermaid-svg-mvLxxSJ3s79roEa9 .node circle,#mermaid-svg-mvLxxSJ3s79roEa9 .node ellipse,#mermaid-svg-mvLxxSJ3s79roEa9 .node polygon,#mermaid-svg-mvLxxSJ3s79roEa9 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-mvLxxSJ3s79roEa9 .node .label{text-align:center;}#mermaid-svg-mvLxxSJ3s79roEa9 .node.clickable{cursor:pointer;}#mermaid-svg-mvLxxSJ3s79roEa9 .arrowheadPath{fill:#333333;}#mermaid-svg-mvLxxSJ3s79roEa9 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-mvLxxSJ3s79roEa9 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-mvLxxSJ3s79roEa9 .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-mvLxxSJ3s79roEa9 .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-mvLxxSJ3s79roEa9 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-mvLxxSJ3s79roEa9 .cluster text{fill:#333;}#mermaid-svg-mvLxxSJ3s79roEa9 .cluster span{color:#333;}#mermaid-svg-mvLxxSJ3s79roEa9 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-mvLxxSJ3s79roEa9 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} UHT生成xxx.generated.h和xxx.gen.cpp反射信息文件 利用static变量的初始化预注册 注册完成的反射信息 UHT与宏 在编写ue代码时相比大家一定遇到过类似于UCLASSGENERATED_BODYUFUNCTION这些宏这些宏其实就是给UHT的一个标记UHT更具这些宏生成generated.h和gen.cpp文件这些宏在ObjectMarcos.h文件中可以找到详细的定义。现在我们来一步一步拨开这些宏背后所做的事情 比如现在我们有这样一个AGhost类 UCLASS(config Ghost) class LEARNUE_API AGhost : public AActor, public FTickableGameObject {GENERATED_BODY() public:virtual void BeginPlay() override;virtual void Tick(float DeltaTime) override;AGhost();virtual ~AGhost() override;UFUNCTION(BlueprintCallable)void PtLog(int i);public:UPROPERTY(VisibleAnywhere)int32 m_time ; };UCLASS 我们首先来看UCLASS宏的定义 #if UE_BUILD_DOCS || defined(__INTELLISENSE__ ) #define UCLASS(...) #else #define UCLASS(...) BODY_MACRO_COMBINE(CURRENT_FILE_ID,_,__LINE__,_PROLOG) #endif#define BODY_MACRO_COMBINE_INNER(A,B,C,D) A##B##C##D #define BODY_MACRO_COMBINE(A,B,C,D) BODY_MACRO_COMBINE_INNER(A,B,C,D)可以发现UCLASS这个宏仅仅是将三个字符串拼接起来。CURRENT_FILE_ID代表一个唯一的文件idLINE为当前行号。 最后这个UCLASS会被替换成空行我猜想是UCLASS宏内的参数在UHT运行的过程中被替换成flag之类的东西所以这后续编译时候就没用了 接着我们来看看UHT生成genrated.h文件可以发现这样的一个宏 #undef CURRENT_FILE_ID #define CURRENT_FILE_ID FID_UeProject_learnUe_Source_learnUe_Ghost_h#define FID_UeProject_learnUe_Source_learnUe_Ghost_h_13_PROLOG发现确实在最后UCLASS这个宏会被替换成空行。 GENERATED_BODY GENERATED_BODY宏和UCLASS宏类似也是拼接事先定义好内容然后进行宏替换不过GENERATED_BODY宏有着实际的替换内容。 #define BODY_MACRO_COMBINE_INNER(A,B,C,D) A##B##C##D #define BODY_MACRO_COMBINE(A,B,C,D) BODY_MACRO_COMBINE_INNER(A,B,C,D)#define GENERATED_BODY(...) BODY_MACRO_COMBINE(CURRENT_FILE_ID,_,__LINE__,_GENERATED_BODY);然后GENERATED_BODY宏实际定义的东西在generated.h文件中 #define FID_UeProject_learnUe_Source_learnUe_Ghost_h_16_GENERATED_BODY \ PRAGMA_DISABLE_DEPRECATION_WARNINGS \ public: \FID_UeProject_learnUe_Source_learnUe_Ghost_h_16_SPARSE_DATA \FID_UeProject_learnUe_Source_learnUe_Ghost_h_16_RPC_WRAPPERS_NO_PURE_DECLS \FID_UeProject_learnUe_Source_learnUe_Ghost_h_16_ACCESSORS \FID_UeProject_learnUe_Source_learnUe_Ghost_h_16_INCLASS_NO_PURE_DECLS \FID_UeProject_learnUe_Source_learnUe_Ghost_h_16_ENHANCED_CONSTRUCTORS \ private: \发现是宏套宏的套娃不过被急还有好多层套者呢。如果不想细看的朋友只要知道这些东西就是UHT帮助生成的代码。 SPARSE_DATA为稀疏数据的定义WRAPPERS_NO_PURE_DECLS为UFunction的定义ACCESSORS这个目前不太确定是啥 INCLASS_NO_PURE_DECLS为序列化StaticClass函数Flag等一些的定义DECLARE_VTABLE_PTR_HELPER_CTOR为默认构造函数Vtable的定义。接下来我们一个一个拆这看。 RPC_WRAPPERS_NO_PURE_DECLS #define FID_UeProject_learnUe_Source_learnUe_Ghost_h_16_RPC_WRAPPERS \\DECLARE_FUNCTION(execPtLog);我们同样可以在generated.h文件中找到这个宏的定义发现是又套娃了一层DECLARE_FUNCTION的宏宏的参数就是UFNCTION函数名接着看看DECLARE_FUNCTION这个宏又做了什么。 #define DECLARE_FUNCTION(func) static void func( UObject* Context, FFrame Stack, RESULT_DECL )可以发现UFUNCTION宏会被UHT生成一个类内静态函数这个类内静态函数的实现在对应的gen.cpp文件中 DEFINE_FUNCTION(func) void func( UObject* Context, FFrame Stack, RESULT_DECL )DEFINE_FUNCTION(AGhost::execPtLog){P_GET_PROPERTY(FIntProperty,Z_Param_i);P_FINISH;P_NATIVE_BEGIN;P_THIS-PtLog(Z_Param_i);P_NATIVE_END;}把这段全是宏的代码展开 void AGhost::execPtLog( UObject* Context, FFrame Stack, RESULT_DECL ) {FIntProperty::TCppType Z_Param_i PropertyType::GetDefaultPropertyValue();Stack.StepCompiledInFIntProperty(Z_Param_i);Stack.Code !!Stack.Code;((AGhost*)(Context))-PtLog(Z_Param_i); } Context其实就是执行AGhost实体参数类型为UObject*但是实际上是AGhost*这里利用的UObject做类型擦除就和void*一样。 Stack为参数比较好理解。 这个函数会由对应的UFunction::Invoke函数调用完成反射函数的调用。 ACCESSORS 暂时不知道是做什么pass INCLASS_NO_PURE_DECLS #define FID_UeProject_learnUe_Source_learnUe_Ghost_h_16_INCLASS_NO_PURE_DECLS \ private: \static void StaticRegisterNativesAGhost(); \friend struct Z_Construct_UClass_AGhost_Statics; \ public: \DECLARE_CLASS(AGhost, AActor, COMPILED_IN_FLAGS(0 | CLASS_Config), CASTCLASS_None, TEXT(/Script/learnUe), NO_API) \DECLARE_SERIALIZER(AGhost) \static const TCHAR* StaticConfigName() {return TEXT(Ghost);} \StaticRegisterNativesAGhost()函数的作用是向自己对应的Uclass类注册UFUNCTION这个函数的定义在对应的gen.cpp中 void AGhost::StaticRegisterNativesAGhost(){UClass* Class AGhost::StaticClass();static const FNameNativePtrPair Funcs[] {{ PtLog, AGhost::execPtLog },};FNativeFunctionRegistrar::RegisterFunctions(Class, Funcs, UE_ARRAY_COUNT(Funcs));}DECLARE_CLASS宏则是定义一些UE类必有的内容如StaticClassStaticPackagenewdelete等必要的东西。 DECLARE_SERIALIZER宏看名字就很容易猜出来必然是与序列化相关 #define DECLARE_SERIALIZER( TClass ) \friend FArchive operator( FArchive Ar, TClass* Res ) \{ \return Ar (UObject*)Res; \} \friend void operator(FStructuredArchive::FSlot InSlot, TClass* Res) \{ \InSlot (UObject*)Res; \}STANDARD_CONSTRUCTORS #define FID_UeProject_learnUe_Source_learnUe_Ghost_h_16_ENHANCED_CONSTRUCTORS \ private: \/** Private move- and copy-constructors, should never be used */ \NO_API AGhost(AGhost); \NO_API AGhost(const AGhost); \ public: \DECLARE_VTABLE_PTR_HELPER_CTOR(NO_API, AGhost); \DEFINE_VTABLE_PTR_HELPER_CTOR_CALLER(AGhost); \DEFINE_DEFAULT_CONSTRUCTOR_CALL(AGhost) STANDARD_CONSTRUCTORS宏禁止了移动和拷贝并定义了DEAFULT_CONSTRUCTOR,需要注意的是这个并不是定义了默认的构造函数 #define DEFINE_DEFAULT_CONSTRUCTOR_CALL(TClass) \static void __DefaultConstructor(const FObjectInitializer X) { new((EInternal*)X.GetObj())TClass; }到此为止.h和gen.h文件中的宏就展开完毕了。 反射信息注册 ue中反射信息是分段注册的由static结构体的构造为第一段执行在main函数之前第二段在ue启动时完成真正的注册。 反射的信息几乎都在对应类的gen.cpp文件中这也是由UHT生成的。 在gen.cpp文件中ue会生成一个每个类唯一的FClassRegistrationInfo变量这个变量与GetPrivateStaticClass函数定义在gen.cpp文件中的IMPLEMENT_CLASS_NO_AUTO_REGISTRATION宏中这个变量就包含了类的信息。 FClassRegistrationInfo IMPLEMENT_CLASS_NO_AUTO_REGISTRATION(AGhost);#define IMPLEMENT_CLASS_NO_AUTO_REGISTRATION(TClass) \FClassRegistrationInfo Z_Registration_Info_UClass_##TClass; \UClass* TClass::GetPrivateStaticClass() \{ \if (!Z_Registration_Info_UClass_##TClass.InnerSingleton) \{ \/* this could be handled with templates, but we want it external to avoid code bloat */ \GetPrivateStaticClassBody( \StaticPackage(), \(TCHAR*)TEXT(#TClass) 1 ((StaticClassFlags CLASS_Deprecated) ? 11 : 0), \Z_Registration_Info_UClass_##TClass.InnerSingleton, \StaticRegisterNatives##TClass, \sizeof(TClass), \alignof(TClass), \(EClassFlags)TClass::StaticClassFlags, \TClass::StaticClassCastFlags(), \TClass::StaticConfigName(), \(UClass::ClassConstructorType)InternalConstructorTClass, \(UClass::ClassVTableHelperCtorCallerType)InternalVTableHelperCtorCallerTClass, \UOBJECT_CPPCLASS_STATICFUNCTIONS_FORCLASS(TClass), \TClass::Super::StaticClass, \TClass::WithinClass::StaticClass \); \} \return Z_Registration_Info_UClass_##TClass.InnerSingleton; \}IMPLEMENT_CLASS_NO_AUTO_REGISTRATION宏中定义了FClassRegistrationInfo类的对象和GetPrivateStaticClass函数GetPrivateStaticClass函数可能大家不熟但是StaticClass大家一定知道其实StaticClass内部调用的就是GetPrivateStaticClass函数。 GetPrivateStaticClassBody的本质是在第一次调用时通过GetPrivateStaticClassBody函数生成一个uclass给Z_Registration_Info_UClass_##TClass.InnerSingleton参数。 GetPrivateStaticClassBody函数是比较长的但是也比较简单 void GetPrivateStaticClassBody(const TCHAR* PackageName,const TCHAR* Name,UClass* ReturnClass,void(*RegisterNativeFunc)(),uint32 InSize,uint32 InAlignment,EClassFlags InClassFlags,EClassCastFlags InClassCastFlags,const TCHAR* InConfigName,UClass::ClassConstructorType InClassConstructor,UClass::ClassVTableHelperCtorCallerType InClassVTableHelperCtorCaller,FUObjectCppClassStaticFunctions InCppClassStaticFunctions,UClass::StaticClassFunctionType InSuperClassFn,UClass::StaticClassFunctionType InWithinClassFn) { #if WITH_RELOADif (IsReloadActive() GetActiveReloadType() ! EActiveReloadType::Reinstancing){UPackage* Package FindPackage(NULL, PackageName);if (Package){ReturnClass FindObjectUClass((UObject *)Package, Name);if (ReturnClass){if (ReturnClass-HotReloadPrivateStaticClass(InSize,InClassFlags,InClassCastFlags,InConfigName,InClassConstructor,InClassVTableHelperCtorCaller,FUObjectCppClassStaticFunctions(InCppClassStaticFunctions),InSuperClassFn(),InWithinClassFn())){// Register the classs native functions.RegisterNativeFunc();}return;}else{UE_LOG(LogClass, Log, TEXT(Could not find existing class %s in package %s for reload, assuming new or modified class), Name, PackageName);}}else{UE_LOG(LogClass, Log, TEXT(Could not find existing package %s for reload of class %s, assuming a new package.), PackageName, Name);}} #endifReturnClass (UClass*)GUObjectAllocator.AllocateUObject(sizeof(UClass), alignof(UClass), true);ReturnClass ::new (ReturnClass)UClass(EC_StaticConstructor,Name,InSize,InAlignment,InClassFlags,InClassCastFlags,InConfigName,EObjectFlags(RF_Public | RF_Standalone | RF_Transient | RF_MarkAsNative | RF_MarkAsRootSet),InClassConstructor,InClassVTableHelperCtorCaller,MoveTemp(InCppClassStaticFunctions));check(ReturnClass);InitializePrivateStaticClass(InSuperClassFn(),ReturnClass,InWithinClassFn(),PackageName,Name);// Register the classs native functions.RegisterNativeFunc(); }简单来说就是如果是热重载则执行HotReloadPrivateStaticClass如果不是则new一个uclass类型出来然后如果有继承关系则设置子父类的关系最后调用参数RegisterNativeFunc函数。RegisterNativeFunc为gen.cpp文件中的StaticRegisterNatives开头加类名的函数作用是注册类内拥有UFUNCTION宏的函数 void AGhost::StaticRegisterNativesAGhost(){UClass* Class AGhost::StaticClass();static const FNameNativePtrPair Funcs[] {{ PtLog, AGhost::execPtLog },};FNativeFunctionRegistrar::RegisterFunctions(Class, Funcs, UE_ARRAY_COUNT(Funcs));}利用static变量 ue利用static变量的初始化进行预注册预注册指的是仅收集谁是要注册的类不进行真正的注册真正的注册等到程序起来后在进行我猜测ue不在static初始化时就注册完全是因为如果都在static初始化时注册程序启动时耗费时间比较长会被误以为卡死之类的。 接下来我们来看ue是怎么利用static变量的初始化进行注册的。在gen.cpp文件中有着这么一个静态变量 static FRegisterCompiledInInfo Z_CompiledInDeferFile_FID_UeProject_learnUe_Source_learnUe_Ghost_h_3523060098(TEXT(/Script/learnUe),Z_CompiledInDeferFile_FID_UeProject_learnUe_Source_learnUe_Ghost_h_Statics::ClassInfo, UE_ARRAY_COUNT(Z_CompiledInDeferFile_FID_UeProject_learnUe_Source_learnUe_Ghost_h_Statics::ClassInfo),nullptr, 0,nullptr, 0); FRegisterCompiledInInfo类型就是ue封装好的一个我们看下它的本质 struct FRegisterCompiledInInfo {template typename ... ArgsFRegisterCompiledInInfo(Args ... args){RegisterCompiledInInfo(std::forwardArgs(args)...);} };void RegisterCompiledInInfo(class UClass* (*InOuterRegister)(), class UClass* (*InInnerRegister)(), const TCHAR* InPackageName, const TCHAR* InName, FClassRegistrationInfo InInfo, const FClassReloadVersionInfo InVersionInfo) {check(InOuterRegister);check(InInnerRegister);FClassDeferredRegistry::AddResult result FClassDeferredRegistry::Get().AddRegistration(InOuterRegister, InInnerRegister, InPackageName, InName, InInfo, InVersionInfo); #if WITH_RELOADif (result FClassDeferredRegistry::AddResult::ExistingChanged !IsReloadActive()){// Class exists, this can only happen during hot-reload or live codingUE_LOG(LogUObjectBase, Fatal, TEXT(Trying to recreate changed class %s outside of hot reload and live coding!), InName);} #endifFString NoPrefix(UObjectBase::RemoveClassPrefix(InName));NotifyRegistrationEvent(InPackageName, *NoPrefix, ENotifyRegistrationType::NRT_Class, ENotifyRegistrationPhase::NRP_Added, (UObject * (*)())(InOuterRegister), false);NotifyRegistrationEvent(InPackageName, *(FString(DEFAULT_OBJECT_PREFIX) NoPrefix), ENotifyRegistrationType::NRT_ClassCDO, ENotifyRegistrationPhase::NRP_Added, (UObject * (*)())(InOuterRegister), false); }在构造时候则执行RegisterCompiledInInfo函数顺带转发参数。顺带一提RegisterCompiledInInfo函数有多个重载我这里仅展示UCLASS的重载实际上UEnumUStruc调用的都是不同的RegisterCompiledInInfo函数 FStructDeferredRegistry可以简单理解成一个模板数组数组里存的是AddRegistration函数的参数信息。虽然实际上FStructDeferredRegistry内部就是数组结构但是内部信息做了一定的封装。在ue中classenumstuct和package都有自己的DeferredRegistry如FClassDeferredRegistry的声明处。 using FClassDeferredRegistry TDeferredRegistryFClassRegistrationInfo; using FEnumDeferredRegistry TDeferredRegistryFEnumRegistrationInfo; using FStructDeferredRegistry TDeferredRegistryFStructRegistrationInfo; using FPackageDeferredRegistry TDeferredRegistryFPackageRegistrationInfo;接着AddRegistration函数和NotifyRegistrationEvent分别注册了InOuterRegister的函数指针和InInnerRegister函数指针这个两个函数指针实际上也是gen.cpp文件中生成的函数。分别为Z_Construct_UClass类名的函数和StaticClass函数不过这里先放一放。我们先看AddRegistration函数做了什么。 /// summary/// Adds the given registration information for the given object. Objects are either classes, structs, or enumerations./// /summary/// param nameInOuterRegisterReturns a fully initialize instance of the object/param/// param nameInInnerRegisterReturns an allocated but uninitialized instance of the object. This is used only by UClass./param/// param nameInPackageNameName of the package/param/// param nameInNameName of the object/param/// param nameInInfoPersistent information about the object/param/// param nameInVersionVersion information for this incarnation of the object/paramAddResult AddRegistration(TType* (*InOuterRegister)(), TType* (*InInnerRegister)(), const TCHAR* InPackageName, const TCHAR* InName, TInfo InInfo, const TVersion InVersion){ #if WITH_RELOADconst FPackageAndNameKey Key FPackageAndNameKey{ InPackageName, InName };TInfo** ExistingInfo InfoMap.Find(Key);bool bHasChanged !ExistingInfo || (*ExistingInfo)-ReloadVersionInfo ! InVersion;InInfo.ReloadVersionInfo InVersion;TType* OldSingleton ExistingInfo ? ((*ExistingInfo)-InnerSingleton ? (*ExistingInfo)-InnerSingleton : (*ExistingInfo)-OuterSingleton) : nullptr;bool bAdd true;if (ExistingInfo){if (IReload* Reload GetActiveReloadInterface()){bAdd Reload-GetEnableReinstancing(bHasChanged);}if (bAdd){if (!bHasChanged){// With live coding, the existing might be the same as the new info. // We still invoke the copy method to allow UClasses to clear the singletons.UpdateSingletons(InInfo, **ExistingInfo);}*ExistingInfo InInfo;}}else{InfoMap.Add(Key, InInfo);}if (bAdd){Registrations.Add(FRegistrant{ InOuterRegister, InInnerRegister, InPackageName, InInfo, OldSingleton, bHasChanged });}return ExistingInfo nullptr ? AddResult::New : (bHasChanged ? AddResult::ExistingChanged : AddResult::ExistingNoChange); #elseRegistrations.Add(FRegistrant{ InOuterRegister, InInnerRegister, InPackageName, InInfo });return AddResult::New; #endif}AddRegistration函数的逻辑是现在自身map上找一下是否存在要add的类如果有则看下是否为热重载如果没有则加入map最后在把信息包装成FRegistrant放入自身的Registrations数组中待后续使用。 然后回到RegisterCompiledInInfo函数在AddRegistration后又调用了NotifyRegistrationEvent函数看名字是通知什么模块有注册事件。 TUniquePtrIAsyncPackageLoader GPackageLoader;void NotifyRegistrationEvent(const TCHAR* PackageName, const TCHAR* Name, ENotifyRegistrationType NotifyRegistrationType, ENotifyRegistrationPhase NotifyRegistrationPhase, UObject *(*InRegister)(), bool InbDynamic, UObject* FinishedObject) {LLM_SCOPE(ELLMTag::AsyncLoading);if (GPackageLoader){GPackageLoader-NotifyRegistrationEvent(PackageName, Name, NotifyRegistrationType, NotifyRegistrationPhase, InRegister, InbDynamic, FinishedObject);}else{GetEarlyRegistrationEventsRecorder().NotifyRegistrationEvent(PackageName, Name, NotifyRegistrationType, NotifyRegistrationPhase, InRegister, InbDynamic, FinishedObject);} }值得注意的是这里GPackageLoader的类型声明上是IAsyncPackageLoader但是实际上是FAsyncLoadingThread这两个类是父子关系函数为虚函数c里很经典的一种用法所以GPackageLoader-NotifyRegistrationEvent调用的实际上是FAsyncLoadingThread-NotifyRegistrationEvent,来看下这个函数做了什么 struct FEDLBootNotificationManager EDLBootNotificationManager;void FAsyncLoadingThread::NotifyRegistrationEvent(const TCHAR* PackageName, const TCHAR* Name, ENotifyRegistrationType NotifyRegistrationType, ENotifyRegistrationPhase NotifyRegistrationPhase, UObject* (*InRegister)(), bool InbDynamic, UObject* FinishedObject) {EDLBootNotificationManager.NotifyRegistrationEvent(PackageName, Name, NotifyRegistrationType, NotifyRegistrationPhase, InRegister, InbDynamic); }emmm看这变量名字是这EDLBoot又代表啥缩写晕查了下大概一个ue启动时辅助初始化的东东。暂时不太明白作用。 inner注册 我们知道了ue利用static变量在main函数之前注册了一些信息现在我来看看ue是如使用这些DeferredRegistry 变量的。 在ue启动时大概的时间点是在loadModule时会执行一个一个叫做UClassRegisterAllCompiledInClasses的函数。 void UClassRegisterAllCompiledInClasses() { #if WITH_RELOADTArrayUClass* AddedClasses; #endifSCOPED_BOOT_TIMING(UClassRegisterAllCompiledInClasses);FClassDeferredRegistry Registry FClassDeferredRegistry::Get();Registry.ProcessChangedObjects();for (const FClassDeferredRegistry::FRegistrant Registrant : Registry.GetRegistrations()){UClass* RegisteredClass FClassDeferredRegistry::InnerRegister(Registrant); #if WITH_RELOADif (IsReloadActive() Registrant.OldSingleton nullptr){AddedClasses.Add(RegisteredClass);} #endif}#if WITH_RELOADif (AddedClasses.Num() 0){FCoreUObjectDelegates::ReloadAddedClassesDelegate.Broadcast(AddedClasses);PRAGMA_DISABLE_DEPRECATION_WARNINGSFCoreUObjectDelegates::RegisterHotReloadAddedClassesDelegate.Broadcast(AddedClasses);PRAGMA_ENABLE_DEPRECATION_WARNINGS} #endif }FClassDeferredRegistry::Get()其实就是获取单例然后将之前利用static变量注册进去的类执行InnerRegiste函数指针这个InnerRegiste是之前gen.cpp文件中的那个StaticClass函数其内部就是我们一开始说的GetPrivateStaticClass函数。它实例化出了uclass类并赋予信息但是到这里还没有完到这里uclass仅仅只有一些ue对类的附加信息如flagconfigname等类内成员和类内函数的信息没有注册到uclass如果细心一点会注意到gen。cpp文件中不仅有inner还有outer 后面的outer就是注册类内成员和类内成员函数的 outer注册 在gen.cpp的文件中有着这样的一个函数它名字是Z_Construct_UClass_类名 在我的AGhost类中它为Z_Construct_UClass_AGhost 。 UClass* Z_Construct_UClass_AGhost(){if (!Z_Registration_Info_UClass_AGhost.OuterSingleton){UECodeGen_Private::ConstructUClass(Z_Registration_Info_UClass_AGhost.OuterSingleton, Z_Construct_UClass_AGhost_Statics::ClassParams);}return Z_Registration_Info_UClass_AGhost.OuterSingleton;}内部使用了UECodeGen_Private::ConstructUClass进行构造outer参数呢是熟悉的Z_Registration_Info_UClass_AGhost就是那个staticclass函数里用的那个。同时也是和inner一样只需要构建一次。 我们接下来看看这个ConstructUClass做了什么 void ConstructUClass(UClass* OutClass, const FClassParams Params){if (OutClass (OutClass-ClassFlags CLASS_Constructed)){return;}for (UObject* (*const *SingletonFunc)() Params.DependencySingletonFuncArray, *(*const *SingletonFuncEnd)() SingletonFunc Params.NumDependencySingletons; SingletonFunc ! SingletonFuncEnd; SingletonFunc){(*SingletonFunc)();}UClass* NewClass Params.ClassNoRegisterFunc();OutClass NewClass;if (NewClass-ClassFlags CLASS_Constructed){return;}UObjectForceRegistration(NewClass);UClass* SuperClass NewClass-GetSuperClass();if (SuperClass){NewClass-ClassFlags | (SuperClass-ClassFlags CLASS_Inherit);}NewClass-ClassFlags | (EClassFlags)(Params.ClassFlags | CLASS_Constructed);// Make sure the reference token stream is empty since it will be reconstructed later on// This should not apply to intrinsic classes since they emit native references before AssembleReferenceTokenStream is called.if ((NewClass-ClassFlags CLASS_Intrinsic) ! CLASS_Intrinsic){check((NewClass-ClassFlags CLASS_TokenStreamAssembled) ! CLASS_TokenStreamAssembled);NewClass-ReferenceTokenStream.Empty();}NewClass-CreateLinkAndAddChildFunctionsToMap(Params.FunctionLinkArray, Params.NumFunctions);ConstructFProperties(NewClass, Params.PropertyArray, Params.NumProperties);if (Params.ClassConfigNameUTF8){NewClass-ClassConfigName FName(UTF8_TO_TCHAR(Params.ClassConfigNameUTF8));}NewClass-SetCppTypeInfoStatic(Params.CppClassInfo);if (int32 NumImplementedInterfaces Params.NumImplementedInterfaces){NewClass-Interfaces.Reserve(NumImplementedInterfaces);for (const FImplementedInterfaceParams* ImplementedInterface Params.ImplementedInterfaceArray, *ImplementedInterfaceEnd ImplementedInterface NumImplementedInterfaces; ImplementedInterface ! ImplementedInterfaceEnd; ImplementedInterface){UClass* (*ClassFunc)() ImplementedInterface-ClassFunc;UClass* InterfaceClass ClassFunc ? ClassFunc() : nullptr;NewClass-Interfaces.Emplace(InterfaceClass, ImplementedInterface-Offset, ImplementedInterface-bImplementedByK2);}}#if WITH_METADATAAddMetaData(NewClass, Params.MetaDataArray, Params.NumMetaData); #endifNewClass-StaticLink();NewClass-SetSparseClassDataStruct(NewClass-GetSparseClassDataArchetypeStruct());} } 可以看到首先执行了parm.DependencySingletonFuncArray参数中所有的函数指针而这个parm在gen.cpp文件是个叫ClassParams的FClassParmas的结构体里面存放着UFuntion的信息。 const UECodeGen_Private::FClassParams Z_Construct_UClass_AGhost_Statics::ClassParams {AGhost::StaticClass,Ghost,StaticCppClassTypeInfo,DependentSingletons,FuncInfo,Z_Construct_UClass_AGhost_Statics::PropPointers,nullptr,UE_ARRAY_COUNT(DependentSingletons),UE_ARRAY_COUNT(FuncInfo),UE_ARRAY_COUNT(Z_Construct_UClass_AGhost_Statics::PropPointers),0,0x009000A4u,METADATA_PARAMS(Z_Construct_UClass_AGhost_Statics::Class_MetaDataParams, UE_ARRAY_COUNT(Z_Construct_UClass_AGhost_Statics::Class_MetaDataParams))};//FclassParms定义struct FClassParams{UClass* (*ClassNoRegisterFunc)();const char* ClassConfigNameUTF8;const FCppClassTypeInfoStatic* CppClassInfo;UObject* (*const *DependencySingletonFuncArray)();const FClassFunctionLinkInfo* FunctionLinkArray;const FPropertyParamsBase* const* PropertyArray;const FImplementedInterfaceParams* ImplementedInterfaceArray;int32 NumDependencySingletons;int32 NumFunctions;int32 NumProperties;int32 NumImplementedInterfaces;uint32 ClassFlags; // EClassFlags #if WITH_METADATAconst FMetaDataPairParam* MetaDataArray;int32 NumMetaData; #endif};ConstructUClass函数主要就是利用FClassParams去构建Uclass的信息如果全部展开篇幅实在是太太长了我也写不动啦想摸了。有兴趣可以自行找下生成的gen.cpp文件基本都在那里啦。 副案例代码 //cpp //Ghost.gen.cpp // Copyright Epic Games, Inc. All Rights Reserved. /*Generated code exported from UnrealHeaderTool.DO NOT modify this manually! Edit the corresponding .h files instead! */#include UObject/GeneratedCppIncludes.h #include learnUe/Ghost.h PRAGMA_DISABLE_DEPRECATION_WARNINGS void EmptyLinkFunctionForGeneratedCodeGhost() {} // Cross Module ReferencesENGINE_API UClass* Z_Construct_UClass_AActor();LEARNUE_API UClass* Z_Construct_UClass_AGhost();LEARNUE_API UClass* Z_Construct_UClass_AGhost_NoRegister();UPackage* Z_Construct_UPackage__Script_learnUe(); // End Cross Module ReferencesDEFINE_FUNCTION(AGhost::execPtLog){P_GET_PROPERTY(FIntProperty,Z_Param_i);P_FINISH;P_NATIVE_BEGIN;P_THIS-PtLog(Z_Param_i);P_NATIVE_END;}void AGhost::StaticRegisterNativesAGhost(){UClass* Class AGhost::StaticClass();static const FNameNativePtrPair Funcs[] {{ PtLog, AGhost::execPtLog },};FNativeFunctionRegistrar::RegisterFunctions(Class, Funcs, UE_ARRAY_COUNT(Funcs));}struct Z_Construct_UFunction_AGhost_PtLog_Statics{struct Ghost_eventPtLog_Parms{int32 i;};static const UECodeGen_Private::FUnsizedIntPropertyParams NewProp_i;static const UECodeGen_Private::FPropertyParamsBase* const PropPointers[]; #if WITH_METADATAstatic const UECodeGen_Private::FMetaDataPairParam Function_MetaDataParams[]; #endifstatic const UECodeGen_Private::FFunctionParams FuncParams;};const UECodeGen_Private::FUnsizedIntPropertyParams Z_Construct_UFunction_AGhost_PtLog_Statics::NewProp_i { i, nullptr, (EPropertyFlags)0x0010000000000080, UECodeGen_Private::EPropertyGenFlags::Int, RF_Public|RF_Transient|RF_MarkAsNative, 1, nullptr, nullptr, STRUCT_OFFSET(Ghost_eventPtLog_Parms, i), METADATA_PARAMS(nullptr, 0) };const UECodeGen_Private::FPropertyParamsBase* const Z_Construct_UFunction_AGhost_PtLog_Statics::PropPointers[] {(const UECodeGen_Private::FPropertyParamsBase*)Z_Construct_UFunction_AGhost_PtLog_Statics::NewProp_i,}; #if WITH_METADATAconst UECodeGen_Private::FMetaDataPairParam Z_Construct_UFunction_AGhost_PtLog_Statics::Function_MetaDataParams[] {{ ModuleRelativePath, Ghost.h },}; #endifconst UECodeGen_Private::FFunctionParams Z_Construct_UFunction_AGhost_PtLog_Statics::FuncParams { (UObject*(*)())Z_Construct_UClass_AGhost, nullptr, PtLog, nullptr, nullptr, sizeof(Z_Construct_UFunction_AGhost_PtLog_Statics::Ghost_eventPtLog_Parms), Z_Construct_UFunction_AGhost_PtLog_Statics::PropPointers, UE_ARRAY_COUNT(Z_Construct_UFunction_AGhost_PtLog_Statics::PropPointers), RF_Public|RF_Transient|RF_MarkAsNative, (EFunctionFlags)0x04020401, 0, 0, METADATA_PARAMS(Z_Construct_UFunction_AGhost_PtLog_Statics::Function_MetaDataParams, UE_ARRAY_COUNT(Z_Construct_UFunction_AGhost_PtLog_Statics::Function_MetaDataParams)) };UFunction* Z_Construct_UFunction_AGhost_PtLog(){static UFunction* ReturnFunction nullptr;if (!ReturnFunction){UECodeGen_Private::ConstructUFunction(ReturnFunction, Z_Construct_UFunction_AGhost_PtLog_Statics::FuncParams);}return ReturnFunction;}IMPLEMENT_CLASS_NO_AUTO_REGISTRATION(AGhost);UClass* Z_Construct_UClass_AGhost_NoRegister(){return AGhost::StaticClass();}struct Z_Construct_UClass_AGhost_Statics{static UObject* (*const DependentSingletons[])();static const FClassFunctionLinkInfo FuncInfo[]; #if WITH_METADATAstatic const UECodeGen_Private::FMetaDataPairParam Class_MetaDataParams[]; #endif #if WITH_METADATAstatic const UECodeGen_Private::FMetaDataPairParam NewProp_m_time_MetaData[]; #endifstatic const UECodeGen_Private::FIntPropertyParams NewProp_m_time;static const UECodeGen_Private::FPropertyParamsBase* const PropPointers[];static const FCppClassTypeInfoStatic StaticCppClassTypeInfo;static const UECodeGen_Private::FClassParams ClassParams;};UObject* (*const Z_Construct_UClass_AGhost_Statics::DependentSingletons[])() {(UObject* (*)())Z_Construct_UClass_AActor,(UObject* (*)())Z_Construct_UPackage__Script_learnUe,};const FClassFunctionLinkInfo Z_Construct_UClass_AGhost_Statics::FuncInfo[] {{ Z_Construct_UFunction_AGhost_PtLog, PtLog }, // 1286413536}; #if WITH_METADATAconst UECodeGen_Private::FMetaDataPairParam Z_Construct_UClass_AGhost_Statics::Class_MetaDataParams[] {{ IncludePath, Ghost.h },{ ModuleRelativePath, Ghost.h },}; #endif #if WITH_METADATAconst UECodeGen_Private::FMetaDataPairParam Z_Construct_UClass_AGhost_Statics::NewProp_m_time_MetaData[] {{ Category, Ghost },{ ModuleRelativePath, Ghost.h },}; #endifconst UECodeGen_Private::FIntPropertyParams Z_Construct_UClass_AGhost_Statics::NewProp_m_time { m_time, nullptr, (EPropertyFlags)0x0010000000020001, UECodeGen_Private::EPropertyGenFlags::Int, RF_Public|RF_Transient|RF_MarkAsNative, 1, nullptr, nullptr, STRUCT_OFFSET(AGhost, m_time), METADATA_PARAMS(Z_Construct_UClass_AGhost_Statics::NewProp_m_time_MetaData, UE_ARRAY_COUNT(Z_Construct_UClass_AGhost_Statics::NewProp_m_time_MetaData)) };const UECodeGen_Private::FPropertyParamsBase* const Z_Construct_UClass_AGhost_Statics::PropPointers[] {(const UECodeGen_Private::FPropertyParamsBase*)Z_Construct_UClass_AGhost_Statics::NewProp_m_time,};const FCppClassTypeInfoStatic Z_Construct_UClass_AGhost_Statics::StaticCppClassTypeInfo {TCppClassTypeTraitsAGhost::IsAbstract,};const UECodeGen_Private::FClassParams Z_Construct_UClass_AGhost_Statics::ClassParams {AGhost::StaticClass,Ghost,StaticCppClassTypeInfo,DependentSingletons,FuncInfo,Z_Construct_UClass_AGhost_Statics::PropPointers,nullptr,UE_ARRAY_COUNT(DependentSingletons),UE_ARRAY_COUNT(FuncInfo),UE_ARRAY_COUNT(Z_Construct_UClass_AGhost_Statics::PropPointers),0,0x009000A4u,METADATA_PARAMS(Z_Construct_UClass_AGhost_Statics::Class_MetaDataParams, UE_ARRAY_COUNT(Z_Construct_UClass_AGhost_Statics::Class_MetaDataParams))};UClass* Z_Construct_UClass_AGhost(){if (!Z_Registration_Info_UClass_AGhost.OuterSingleton){UECodeGen_Private::ConstructUClass(Z_Registration_Info_UClass_AGhost.OuterSingleton, Z_Construct_UClass_AGhost_Statics::ClassParams);}return Z_Registration_Info_UClass_AGhost.OuterSingleton;}template LEARNUE_API UClass* StaticClassAGhost(){return AGhost::StaticClass();}DEFINE_VTABLE_PTR_HELPER_CTOR(AGhost);struct Z_CompiledInDeferFile_FID_UeProject_learnUe_Source_learnUe_Ghost_h_Statics{static const FClassRegisterCompiledInInfo ClassInfo[];};const FClassRegisterCompiledInInfo Z_CompiledInDeferFile_FID_UeProject_learnUe_Source_learnUe_Ghost_h_Statics::ClassInfo[] {{ Z_Construct_UClass_AGhost, AGhost::StaticClass, TEXT(AGhost), Z_Registration_Info_UClass_AGhost, CONSTRUCT_RELOAD_VERSION_INFO(FClassReloadVersionInfo, sizeof(AGhost), 1620684469U) },};static FRegisterCompiledInInfo Z_CompiledInDeferFile_FID_UeProject_learnUe_Source_learnUe_Ghost_h_3523060098(TEXT(/Script/learnUe),Z_CompiledInDeferFile_FID_UeProject_learnUe_Source_learnUe_Ghost_h_Statics::ClassInfo, UE_ARRAY_COUNT(Z_CompiledInDeferFile_FID_UeProject_learnUe_Source_learnUe_Ghost_h_Statics::ClassInfo),nullptr, 0,nullptr, 0); PRAGMA_ENABLE_DEPRECATION_WARNINGSGhost.h UCLASS(config Ghost) class LEARNUE_API AGhost : public AActor, public FTickableGameObject {GENERATED_BODY() public:virtual void BeginPlay() override;virtual void Tick(float DeltaTime) override;virtual TStatId GetStatId() const override{return Super::GetStatID();}public:AGhost();virtual ~AGhost() override;UFUNCTION(BlueprintCallable)void PtLog(int i);public:FGhostDelegate m_ghostDelegate;UPROPERTY(VisibleAnywhere)int32 m_time ; }; //Ghost.gen.cpp // Copyright Epic Games, Inc. All Rights Reserved. /*Generated code exported from UnrealHeaderTool.DO NOT modify this manually! Edit the corresponding .h files instead! */#include UObject/GeneratedCppIncludes.h #include learnUe/Ghost.h PRAGMA_DISABLE_DEPRECATION_WARNINGS void EmptyLinkFunctionForGeneratedCodeGhost() {} // Cross Module ReferencesENGINE_API UClass* Z_Construct_UClass_AActor();LEARNUE_API UClass* Z_Construct_UClass_AGhost();LEARNUE_API UClass* Z_Construct_UClass_AGhost_NoRegister();UPackage* Z_Construct_UPackage__Script_learnUe(); // End Cross Module ReferencesDEFINE_FUNCTION(AGhost::execPtLog){P_GET_PROPERTY(FIntProperty,Z_Param_i);P_FINISH;P_NATIVE_BEGIN;P_THIS-PtLog(Z_Param_i);P_NATIVE_END;}void AGhost::StaticRegisterNativesAGhost(){UClass* Class AGhost::StaticClass();static const FNameNativePtrPair Funcs[] {{ PtLog, AGhost::execPtLog },};FNativeFunctionRegistrar::RegisterFunctions(Class, Funcs, UE_ARRAY_COUNT(Funcs));}struct Z_Construct_UFunction_AGhost_PtLog_Statics{struct Ghost_eventPtLog_Parms{int32 i;};static const UECodeGen_Private::FUnsizedIntPropertyParams NewProp_i;static const UECodeGen_Private::FPropertyParamsBase* const PropPointers[]; #if WITH_METADATAstatic const UECodeGen_Private::FMetaDataPairParam Function_MetaDataParams[]; #endifstatic const UECodeGen_Private::FFunctionParams FuncParams;};const UECodeGen_Private::FUnsizedIntPropertyParams Z_Construct_UFunction_AGhost_PtLog_Statics::NewProp_i { i, nullptr, (EPropertyFlags)0x0010000000000080, UECodeGen_Private::EPropertyGenFlags::Int, RF_Public|RF_Transient|RF_MarkAsNative, 1, nullptr, nullptr, STRUCT_OFFSET(Ghost_eventPtLog_Parms, i), METADATA_PARAMS(nullptr, 0) };const UECodeGen_Private::FPropertyParamsBase* const Z_Construct_UFunction_AGhost_PtLog_Statics::PropPointers[] {(const UECodeGen_Private::FPropertyParamsBase*)Z_Construct_UFunction_AGhost_PtLog_Statics::NewProp_i,}; #if WITH_METADATAconst UECodeGen_Private::FMetaDataPairParam Z_Construct_UFunction_AGhost_PtLog_Statics::Function_MetaDataParams[] {{ ModuleRelativePath, Ghost.h },}; #endifconst UECodeGen_Private::FFunctionParams Z_Construct_UFunction_AGhost_PtLog_Statics::FuncParams { (UObject*(*)())Z_Construct_UClass_AGhost, nullptr, PtLog, nullptr, nullptr, sizeof(Z_Construct_UFunction_AGhost_PtLog_Statics::Ghost_eventPtLog_Parms), Z_Construct_UFunction_AGhost_PtLog_Statics::PropPointers, UE_ARRAY_COUNT(Z_Construct_UFunction_AGhost_PtLog_Statics::PropPointers), RF_Public|RF_Transient|RF_MarkAsNative, (EFunctionFlags)0x04020401, 0, 0, METADATA_PARAMS(Z_Construct_UFunction_AGhost_PtLog_Statics::Function_MetaDataParams, UE_ARRAY_COUNT(Z_Construct_UFunction_AGhost_PtLog_Statics::Function_MetaDataParams)) };UFunction* Z_Construct_UFunction_AGhost_PtLog(){static UFunction* ReturnFunction nullptr;if (!ReturnFunction){UECodeGen_Private::ConstructUFunction(ReturnFunction, Z_Construct_UFunction_AGhost_PtLog_Statics::FuncParams);}return ReturnFunction;}IMPLEMENT_CLASS_NO_AUTO_REGISTRATION(AGhost);UClass* Z_Construct_UClass_AGhost_NoRegister(){return AGhost::StaticClass();}struct Z_Construct_UClass_AGhost_Statics{static UObject* (*const DependentSingletons[])();static const FClassFunctionLinkInfo FuncInfo[]; #if WITH_METADATAstatic const UECodeGen_Private::FMetaDataPairParam Class_MetaDataParams[]; #endif #if WITH_METADATAstatic const UECodeGen_Private::FMetaDataPairParam NewProp_m_time_MetaData[]; #endifstatic const UECodeGen_Private::FIntPropertyParams NewProp_m_time;static const UECodeGen_Private::FPropertyParamsBase* const PropPointers[];static const FCppClassTypeInfoStatic StaticCppClassTypeInfo;static const UECodeGen_Private::FClassParams ClassParams;};UObject* (*const Z_Construct_UClass_AGhost_Statics::DependentSingletons[])() {(UObject* (*)())Z_Construct_UClass_AActor,(UObject* (*)())Z_Construct_UPackage__Script_learnUe,};const FClassFunctionLinkInfo Z_Construct_UClass_AGhost_Statics::FuncInfo[] {{ Z_Construct_UFunction_AGhost_PtLog, PtLog }, // 1286413536}; #if WITH_METADATAconst UECodeGen_Private::FMetaDataPairParam Z_Construct_UClass_AGhost_Statics::Class_MetaDataParams[] {{ IncludePath, Ghost.h },{ ModuleRelativePath, Ghost.h },}; #endif #if WITH_METADATAconst UECodeGen_Private::FMetaDataPairParam Z_Construct_UClass_AGhost_Statics::NewProp_m_time_MetaData[] {{ Category, Ghost },{ ModuleRelativePath, Ghost.h },}; #endifconst UECodeGen_Private::FIntPropertyParams Z_Construct_UClass_AGhost_Statics::NewProp_m_time { m_time, nullptr, (EPropertyFlags)0x0010000000020001, UECodeGen_Private::EPropertyGenFlags::Int, RF_Public|RF_Transient|RF_MarkAsNative, 1, nullptr, nullptr, STRUCT_OFFSET(AGhost, m_time), METADATA_PARAMS(Z_Construct_UClass_AGhost_Statics::NewProp_m_time_MetaData, UE_ARRAY_COUNT(Z_Construct_UClass_AGhost_Statics::NewProp_m_time_MetaData)) };const UECodeGen_Private::FPropertyParamsBase* const Z_Construct_UClass_AGhost_Statics::PropPointers[] {(const UECodeGen_Private::FPropertyParamsBase*)Z_Construct_UClass_AGhost_Statics::NewProp_m_time,};const FCppClassTypeInfoStatic Z_Construct_UClass_AGhost_Statics::StaticCppClassTypeInfo {TCppClassTypeTraitsAGhost::IsAbstract,};const UECodeGen_Private::FClassParams Z_Construct_UClass_AGhost_Statics::ClassParams {AGhost::StaticClass,Ghost,StaticCppClassTypeInfo,DependentSingletons,FuncInfo,Z_Construct_UClass_AGhost_Statics::PropPointers,nullptr,UE_ARRAY_COUNT(DependentSingletons),UE_ARRAY_COUNT(FuncInfo),UE_ARRAY_COUNT(Z_Construct_UClass_AGhost_Statics::PropPointers),0,0x009000A4u,METADATA_PARAMS(Z_Construct_UClass_AGhost_Statics::Class_MetaDataParams, UE_ARRAY_COUNT(Z_Construct_UClass_AGhost_Statics::Class_MetaDataParams))};UClass* Z_Construct_UClass_AGhost(){if (!Z_Registration_Info_UClass_AGhost.OuterSingleton){UECodeGen_Private::ConstructUClass(Z_Registration_Info_UClass_AGhost.OuterSingleton, Z_Construct_UClass_AGhost_Statics::ClassParams);}return Z_Registration_Info_UClass_AGhost.OuterSingleton;}template LEARNUE_API UClass* StaticClassAGhost(){return AGhost::StaticClass();}DEFINE_VTABLE_PTR_HELPER_CTOR(AGhost);struct Z_CompiledInDeferFile_FID_UeProject_learnUe_Source_learnUe_Ghost_h_Statics{static const FClassRegisterCompiledInInfo ClassInfo[];};const FClassRegisterCompiledInInfo Z_CompiledInDeferFile_FID_UeProject_learnUe_Source_learnUe_Ghost_h_Statics::ClassInfo[] {{ Z_Construct_UClass_AGhost, AGhost::StaticClass, TEXT(AGhost), Z_Registration_Info_UClass_AGhost, CONSTRUCT_RELOAD_VERSION_INFO(FClassReloadVersionInfo, sizeof(AGhost), 1620684469U) },};static FRegisterCompiledInInfo Z_CompiledInDeferFile_FID_UeProject_learnUe_Source_learnUe_Ghost_h_3523060098(TEXT(/Script/learnUe),Z_CompiledInDeferFile_FID_UeProject_learnUe_Source_learnUe_Ghost_h_Statics::ClassInfo, UE_ARRAY_COUNT(Z_CompiledInDeferFile_FID_UeProject_learnUe_Source_learnUe_Ghost_h_Statics::ClassInfo),nullptr, 0,nullptr, 0); PRAGMA_ENABLE_DEPRECATION_WARNINGS
http://www.yutouwan.com/news/498364/

相关文章:

  • 怎么在年报网站做简易注销用自己的服务器建网站
  • 保定网站推广门户网站部署方案
  • 自己服务器做网站主机网站被入侵后需做的检测 1
  • wordpress情侣网站源码成品网站w灬源码伊园
  • 网站栏目 英文北京网站备案核验单
  • wap门户网站个人手机网站
  • 网站开发项目发展现状渗透wordpress
  • 苏州知名高端网站建设机构优化公司流程
  • 深圳私人做网站上海公司网站建设哪家好
  • 上海网站运营wordpress代码
  • asp大型网站开发传奇网站模板免费下载
  • 公司网站招聘费如何做会计分录抖音开放平台是干嘛的
  • 浙江网站建设价格帮企业做网站赚钱
  • 网站建设捌金手指花总十三汕头网站建设方案外包
  • 网站开发实训周报北京企业网络推广方案
  • 外国人做的网站app网站制作下载
  • 外贸建站公司排名西充建设部门投诉网站
  • 公司门户网站该怎么做网页设计做一个网站
  • 互联网宣传推广的基础架构2 网站内部链接优化
  • 做 网站 技术支持 抓获 互助什么专业可以做网站
  • 怎样申请注册公司网站镇江企业网站建设公司
  • 同一个ip的网站做链接有用福州建设人才市场网站
  • 合肥网站开发招聘做一个网站需要哪些资源
  • 郑州区块链数字钱包网站开发周期app制作app定制开发价格
  • 怎么把自己做的网站上传到网上惠州软件开发公司
  • 哪些网站做任务可以赚钱的网站推广策划书
  • 珠海城乡建设网站下载软件的app
  • 长春 网站建设网络推广网页设计但网页打不开
  • 如何网站推广宣传最好使用中文目录
  • 网站seo策划方案案例分析四川网站建设的公司哪家好