UObject
UHT空文件结果分析
一个空文件
#pragma once
#include "CoreMinimal.h"
#include "UObject/Object.h"
#include "Hello.generated.h"
UCLASS()
class TPSPROJECT_API UHello : public UObject
{
GENERATED_BODY()
};
#define GENERATED_BODY(...) BODY_MACRO_COMBINE(CURRENT_FILE_ID,_,__LINE__,_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)
GENERATED_BODY其实就是把文件名行号这些信息拼到一起。结果如下。
FID_MonsterFrame_Source_TPSProject_Hello_h_15_GENERATED_BODY
对这些宏定义的实现往前找,显然在UHT生成的Hello.generated.h中。
文件路径在MonsterFrame\Intermediate\Build\Win64\UnrealEditor\Inc\TPSProject\UHT
// Copyright Epic Games, Inc. All Rights Reserved.
/*=========================================================================<span style="font-weight: bold;" class="mark">
Generated code exported from UnrealHeaderTool.
DO NOT modify this manually! Edit the corresponding .h files instead!
</span>=========================================================================*/
// IWYU pragma: private, include "Hello.h"
#include "UObject/ObjectMacros.h"
#include "UObject/ScriptMacros.h"
PRAGMA_DISABLE_DEPRECATION_WARNINGS
#ifdef TPSPROJECT_Hello_generated_h
#error "Hello.generated.h already included, missing '#pragma once' in Hello.h"
#endif
#define TPSPROJECT_Hello_generated_h
#define FID_MonsterFrame_Source_TPSProject_Hello_h_15_SPARSE_DATA
#define FID_MonsterFrame_Source_TPSProject_Hello_h_15_SPARSE_DATA_PROPERTY_ACCESSORS
#define FID_MonsterFrame_Source_TPSProject_Hello_h_15_EDITOR_ONLY_SPARSE_DATA_PROPERTY_ACCESSORS
#define FID_MonsterFrame_Source_TPSProject_Hello_h_15_RPC_WRAPPERS_NO_PURE_DECLS
#define FID_MonsterFrame_Source_TPSProject_Hello_h_15_ACCESSORS
#define FID_MonsterFrame_Source_TPSProject_Hello_h_15_INCLASS_NO_PURE_DECLS \
private: \
static void StaticRegisterNativesUHello(); \
friend struct Z_Construct_UClass_UHello_Statics; \
public: \
DECLARE_CLASS(UHello, UObject, COMPILED_IN_FLAGS(0), CASTCLASS_None, TEXT("/Script/TPSProject"), NO_API) \
DECLARE_SERIALIZER(UHello)
#define FID_MonsterFrame_Source_TPSProject_Hello_h_15_ENHANCED_CONSTRUCTORS \
/** Standard constructor, called after all reflected properties have been initialized */ \
NO_API UHello(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get()); \
private: \
/** Private move- and copy-constructors, should never be used */ \
NO_API UHello(UHello&&); \
NO_API UHello(const UHello&); \
public: \
DECLARE_VTABLE_PTR_HELPER_CTOR(NO_API, UHello); \
DEFINE_VTABLE_PTR_HELPER_CTOR_CALLER(UHello); \
DEFINE_DEFAULT_OBJECT_INITIALIZER_CONSTRUCTOR_CALL(UHello) \
NO_API virtual ~UHello();
#define FID_MonsterFrame_Source_TPSProject_Hello_h_12_PROLOG
#define FID_MonsterFrame_Source_TPSProject_Hello_h_15_GENERATED_BODY \
PRAGMA_DISABLE_DEPRECATION_WARNINGS \
public: \
FID_MonsterFrame_Source_TPSProject_Hello_h_15_SPARSE_DATA \
FID_MonsterFrame_Source_TPSProject_Hello_h_15_SPARSE_DATA_PROPERTY_ACCESSORS \
FID_MonsterFrame_Source_TPSProject_Hello_h_15_EDITOR_ONLY_SPARSE_DATA_PROPERTY_ACCESSORS \
FID_MonsterFrame_Source_TPSProject_Hello_h_15_RPC_WRAPPERS_NO_PURE_DECLS \
FID_MonsterFrame_Source_TPSProject_Hello_h_15_ACCESSORS \
FID_MonsterFrame_Source_TPSProject_Hello_h_15_INCLASS_NO_PURE_DECLS \
FID_MonsterFrame_Source_TPSProject_Hello_h_15_ENHANCED_CONSTRUCTORS \
private: \
PRAGMA_ENABLE_DEPRECATION_WARNINGS
template<> TPSPROJECT_API UClass* StaticClass<class UHello>();
#undef CURRENT_FILE_ID
#define CURRENT_FILE_ID FID_MonsterFrame_Source_TPSProject_Hello_h
PRAGMA_ENABLE_DEPRECATION_WARNINGS
上面文件最开始包含了两个头文件,其中大部分宏定义在ObjectMacro里能找到。
可以看到空类只有后面两个宏有实际的定义。
#define FID_MonsterFrame_Source_TPSProject_Hello_h_15_INCLASS_NO_PURE_DECLS \
private: \
static void StaticRegisterNativesUHello(); \
friend struct Z_Construct_UClass_UHello_Statics; \
public: \
DECLARE_CLASS(UHello, UObject, COMPILED_IN_FLAGS(0), CASTCLASS_None, TEXT("/Script/TPSProject"), NO_API) \
DECLARE_SERIALIZER(UHello)
#define FID_MonsterFrame_Source_TPSProject_Hello_h_15_ENHANCED_CONSTRUCTORS \
/** Standard constructor, called after all reflected properties have been initialized */ \
NO_API UHello(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get()); \
private: \
/** Private move- and copy-constructors, should never be used */ \
NO_API UHello(UHello&&); \
NO_API UHello(const UHello&); \
public: \
DECLARE_VTABLE_PTR_HELPER_CTOR(NO_API, UHello); \
DEFINE_VTABLE_PTR_HELPER_CTOR_CALLER(UHello); \
DEFINE_DEFAULT_OBJECT_INITIALIZER_CONSTRUCTOR_CALL(UHello) \
NO_API virtual ~UHello();
GENERATED_BODY VS GENERATED_UCLASS_BODY
两者的差别很小,GENERATED_BODY中是NO_API UHello(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get()) : Super(ObjectInitializer) { };
里面多了一个Super(ObjectInitializer) { },多了一个构造函数的默认实现。
意味着GENERATED_BODY里定义和实现都可以。
GENERATED_UCLASS_BODY里宏展开只有一个定义,所以如果使用GENERATED_UCLASS_BODY的话,需要在CPP中补一个定义
UHello::UHello(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer){}
这两个宏里主要是一些构造函数和初始化的工作。
- StaticRegisterNativesUHello 每个UFunction会有一个对应的CFunction,字符串和CFunction的绑定关系在这里生成。有了这个绑定关系,当我们传入字符串的时候,可以查找到对应的CFunction去执行。
- DECLARE_CLASS[1]:对于每一个UObject,需要定义其Class
展开头文件中构造函数的宏
#define DEFINE_DEFAULT_OBJECT_INITIALIZER_CONSTRUCTOR_CALL(TClass) \
static void __DefaultConstructor(const FObjectInitializer& X) { new((EInternal*)X.GetObj())TClass(X); }
template<class T>
void InternalConstructor( const FObjectInitializer& X )
{
T::__DefaultConstructor(X);
}
这里是一种placementnew写法。
在FObjectInitializer中分配好的指针处构造对象。
后面调用静态函数ClassName::__DefaultConstructor(FObjectInitializer)即可完成构造。
DECLARE_CLASS
#define DECLARE_CLASS( TClass, TSuperClass, TStaticFlags, TStaticCastFlags, TPackage, TRequiredAPI ) \ private: \ TClass& operator=(TClass&&); \ TClass& operator=(const TClass&); \ TRequiredAPI static UClass* GetPrivateStaticClass(); \ public: \ /** Bitwise union of #EClassFlags pertaining to this class.*/ \ enum {StaticClassFlags=TStaticFlags}; \ /** Typedef for the base class ({{ typedef-type }}) */ \ typedef TSuperClass Super;\ /** Typedef for {{ typedef-type }}. */ \ typedef TClass ThisClass;\ /** Returns a UClass object representing this class at runtime */ \ inline static UClass* StaticClass() \ { \ return GetPrivateStaticClass(); \ } \ /** Returns the package this class belongs in */ \ inline static const TCHAR* StaticPackage() \ { \ return TPackage; \ } \ /** Returns the static cast flags for this class */ \ inline static EClassCastFlags StaticClassCastFlags() \ { \ return TStaticCastFlags; \ } \ /** For internal use only; use StaticConstructObject() to create new objects. */ \ inline void* operator new(const size_t InSize, EInternal InInternalOnly, UObject* InOuter = (UObject*)GetTransientPackage(), FName InName = NAME_None, EObjectFlags InSetFlags = RF_NoFlags) \ { \ return StaticAllocateObject(StaticClass(), InOuter, InName, InSetFlags); \ } \ /** For internal use only; use StaticConstructObject() to create new objects. */ \ inline void* operator new( const size_t InSize, EInternal* InMem ) \ { \ return (void*)InMem; \ }
首先需要注意的时候这个宏是在UHello类展开的,这里面定义的都是UHello的成员函数。
第一次调用UHello:StaticClass()的时候,会创建一个UClass对象。
具体实现可以看到调用了GetPrivateStaticClass。
通过IMPLEMENT_CLASS在对应的cpp完成了GetPrivateStaticClass的定义。
#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), \ TClass::StaticClassFlags, \ TClass::StaticClassCastFlags(), \ TClass::StaticConfigName(), \ (UClass::ClassConstructorType)InternalConstructor<TClass>, \ (UClass::ClassVTableHelperCtorCallerType)InternalVTableHelperCtorCaller<TClass>, \ UOBJECT_CPPCLASS_STATICFUNCTIONS_FORCLASS(TClass), \ &TClass::Super::StaticClass, \ &TClass::WithinClass::StaticClass \ ); \ } \ return Z_Registration_Info_UClass_##TClass.InnerSingleton; \ }
- GetPrivateStaticClassBody里通过placement new创造了一个UClass对象。
- StaticRegisterNatives##TClass 是nativefun的注册函数,在UClass创造并初始化之后调用。
- GetPrivateStaticClassBody里传入了InternalConstructor函数指针。InternalConstructor函数包裹了类的构造函数,他作为函数指针存到了对应的UClass中(ClassConstructor)。
/** * Helper template to call the default constructor for a class */ template<class T> void InternalConstructor( const FObjectInitializer& X ) { T::__DefaultConstructor(X); } #define DEFINE_DEFAULT_OBJECT_INITIALIZER_CONSTRUCTOR_CALL(TClass) \ static void __DefaultConstructor(const FObjectInitializer& X) { new((EInternal*)X.GetObj())TClass(X); }
在创建一个新对象时经常会走StaticConstructObject_Internal,从UClass对象中会取出这个构造函数的Wrapper。
2024-01-17[2]
STAT(FScopeCycleCounterUObject ConstructorScope(InClass->GetFName().IsNone() ? nullptr : InClass, GET_STATID(STAT_ConstructObject))); (*InClass->ClassConstructor)( FObjectInitializer(Result, InTemplate, Params.bCopyTransientsFromClassDefaults, true, Params.InstanceGraph) );
↩︎
2024-01-17
移动组件每帧不断的去读取动画数据里面的移动Transform,然后应用到实际的胶囊体上面。
0x0000023d26e060a0 (Name="NikkiPlayer_BP_C@1@281474976710657@1")
12 AnimInstance
0x0000023e8bcf8010 (Name="NikkiAnim_BPNew_C"_2147479033)
SelfLoadFileAndRecord : GameBP.WorldMonster.BP.BP_CombatWorldMonster_V2_C
[2024.01.17-15.20.33:278][452]LogUnLua: UNLUA_PRINT[6517] : GameBP/WorldMonster/BP/BP_CombatWorldMonster_V2_C.lua
[2024.01.17-15.20.33:279][452]LogUnLua: UNLUA_PRINT[6517] : SelfLoadFileAndRecord : GameBP.Player.BP_X6PlayerCharacter_C
[2024.01.17-15.20.33:279][452]LogUnLua: UNLUA_PRINT[6517] : GameBP/Player/BP_X6PlayerCharacter_C.lua
[2024.01.17-15.20.33:281][452]LogUnLua: UNLUA_PRINT[6517] : SelfLoadFileAndRecord : GameBP.WorldMonster.Comp.BP_WorldMonsterAnimStatesComp_C
[2024.01.17-15.20.33:281][452]LogUnLua: UNLUA_PRINT[6517] : GameBP/WorldMonster/Comp/BP_WorldMonsterAnimStatesComp_C.lua
[2024.01.17-15.20.33:282][452]LogUnLua: UNLUA_PRINT[6517] : SelfLoadFileAndRecord : GameBP.Combat.Comp.BP_CombatPassiveCollisionComponent_C
[2024.01.17-15.20.33:282][452]LogUnLua: UNLUA_PRINT[6517] : GameBP/Combat/Comp/BP_CombatPassiveCollisionComponent_C.lua
[2024.01.17-15.20.33:282][452]LogUnLua: UNLUA_PRINT[6517] : SelfLoadFileAndRecord : GameBP.Interaction.Abyss.DamageTypeUtils
[2024.01.17-15.20.33:282][452]LogUnLua: UNLUA_PRINT[6517] : GameBP/Interaction/Abyss/DamageTypeUtils.lua
[2024.01.17-15.20.33:284][452]LogAIPerception: Warning: UAIPerceptionComponent::OnRegister: Perception Component is being registered with BP_CombatWorldMonster_V2_KaiJia_C@0@562949953423367@3, they are designed to work with AAIControllers!
[2024.01.17-15.20.33:286][452]LogUnLua: [LUA][15:20:33:286][6452][PlayerLifeSpanStateProcessor:100]:[SwitchLifeSpanTemplate] SwitchLifeSpanTemplate:GameBP.Player.PawnRefComps.PlayerFeedBackPerformance.SubLifeSpanStateProcessor.PlayerCommonLifeSpanTemplate OwnerActor:BP_CombatWorldMonster_V2_KaiJia_C@0@562949953423367@3
[2024.01.17-15.20.33:286][452]LogUnLua: UNLUA_PRINT[6517] : SelfLoadFileAndRecord : GameBP.Player.PawnRefComps.PlayerFeedBackPerformance.SelectAnimTypeProcessor
[2024.01.17-15.20.33:286][452]LogUnLua: UNLUA_PRINT[6517] : GameBP/Player/PawnRefComps/PlayerFeedBackPerformance/SelectAnimTypeProcessor.lua
[2024.01.17-15.20.33:286][452]LogUnLua: UNLUA_PRINT[6517] : SelfLoadFileAndRecord : GameBP.Player.PawnRefComps.PlayerFeedBackPerformance.CharacterSituationFeedbackProcessor
[2024.01.17-15.20.33:287][452]LogUnLua: UNLUA_PRINT[6517] : GameBP/Player/PawnRefComps/PlayerFeedBackPerformance/CharacterSituationFeedbackProcessor.lua
[2024.01.17-15.20.33:291][452]LogUnLua: UNLUA_PRINT[6517] : SelfLoadFileAndRecord : Logics.AI.Object.AIObject_Monster
[2024.01.17-15.20.33:291][452]LogUnLua: UNLUA_PRINT[6517] : Logics/AI/Object/AIObject_Monster.lua
[2024.01.17-15.20.33:296][452]LogUnLua: UNLUA_PRINT[6517] : SelfLoadFileAndRecord : Logics.MaterialEffect.MaterialEffectModule
[2024.01.17-15.20.33:296][452]LogUnLua: UNLUA_PRINT[6517] : Logics/MaterialEffect/MaterialEffectModule.lua
[2024.01.17-15.20.33:297][452]LogStreaming: Display: FlushAsyncLoading(1118): 1 QueuedPackages, 39 AsyncPackages
[2024.01.17-15.20.33:303][452]LogUnLua: UNLUA_PRINT[6517] : SelfLoadFileAndRecord : GameBP.PaperAI.BehaviourTree.BTD.BTD_WorldAI_ExitAfterExecution_C
[2024.01.17-15.20.33:303][452]LogUnLua: UNLUA_PRINT[6517] : GameBP/PaperAI/BehaviourTree/BTD/BTD_WorldAI_ExitAfterExecution_C.lua
[2024.01.17-15.20.33:304][452]LogUnLua: UNLUA_PRINT[6517] : SelfLoadFileAndRecord : GameBP.PaperAI.BehaviourTree.BTT.BTT_WorldAI_BackToLocation_C
[2024.01.17-15.20.33:304][452]LogUnLua: UNLUA_PRINT[6517] : GameBP/PaperAI/BehaviourTree/BTT/BTT_WorldAI_BackToLocation_C.lua
[2024.01.17-15.20.33:304][452]LogUnLua: UNLUA_PRINT[6517] : SelfLoadFileAndRecord : GameBP.PaperAI.BehaviourTree.BTT.BTT_WorldAI_GetOriginTransform_C
[2024.01.17-15.20.33:304][452]LogUnLua: UNLUA_PRINT[6517] : GameBP/PaperAI/BehaviourTree/BTT/BTT_WorldAI_GetOriginTransform_C.lua
[2024.01.17-15.20.33:305][452]LogUnLua: UNLUA_PRINT[6517] : SelfLoadFileAndRecord : GameBP.PaperAI.BehaviourTree.BTT.BTT_WorldAI_PlayExitBattleAni_C
[2024.01.17-15.20.33:305][452]LogUnLua: UNLUA_PRINT[6517] : GameBP/PaperAI/BehaviourTree/BTT/BTT_WorldAI_PlayExitBattleAni_C.lua
[2024.01.17-15.20.33:305][452]LogUnLua: UNLUA_PRINT[6517] : SelfLoadFileAndRecord : GameBP.PaperAI.BehaviourTree.BTT.BTT_WorldAI_TeleportTo_C
[2024.01.17-15.20.33:305][452]LogUnLua: UNLUA_PRINT[6517] : GameBP/PaperAI/BehaviourTree/BTT/BTT_WorldAI_TeleportTo_C.lua
[2024.01.17-15.20.33:306][452]LogUnLua: UNLUA_PRINT[6517] : SelfLoadFileAndRecord : GameBP.PaperAI.BehaviourTree.BTS.BTS_WorldAI_FaceToTarget_C
[2024.01.17-15.20.33:306][452]LogUnLua: UNLUA_PRINT[6517] : GameBP/PaperAI/BehaviourTree/BTS/BTS_WorldAI_FaceToTarget_C.lua
[2024.01.17-15.20.33:306][452]LogUnLua: UNLUA_PRINT[6517] : SelfLoadFileAndRecord : GameBP.PaperAI.BehaviourTree.BTS.BTS_WorldAI_SeekTarget_C
[2024.01.17-15.20.33:306][452]LogUnLua: UNLUA_PRINT[6517] : GameBP/PaperAI/BehaviourTree/BTS/BTS_WorldAI_SeekTarget_C.lua
[2024.01.17-15.20.33:307][452]LogUnLua: UNLUA_PRINT[6517] : SelfLoadFileAndRecord : GameBP.PaperAI.BehaviourTree.WorldAIBBKey
[2024.01.17-15.20.33:307][452]LogUnLua: UNLUA_PRINT[6517] : GameBP/PaperAI/BehaviourTree/WorldAIBBKey.lua
[2024.01.17-15.20.33:307][452]LogUnLua: UNLUA_PRINT[6517] : SelfLoadFileAndRecord : GameBP.PaperAI.BehaviourTree.BTS.BTS_WorldAI_SelectMoveDest_C
[2024.01.17-15.20.33:307][452]LogUnLua: UNLUA_PRINT[6517] : GameBP/PaperAI/BehaviourTree/BTS/BTS_WorldAI_SelectMoveDest_C.lua
[2024.01.17-15.20.33:308][452]LogUnLua: UNLUA_PRINT[6517] : SelfLoadFileAndRecord : GameBP.PaperAI.BehaviourTree.BTS.BTS_WorldAI_SelectSkill_C
[2024.01.17-15.20.33:308][452]LogUnLua: UNLUA_PRINT[6517] : GameBP/PaperAI/BehaviourTree/BTS/BTS_WorldAI_SelectSkill_C.lua
[2024.01.17-15.20.33:309][452]LogUnLua: UNLUA_PRINT[6517] : SelfLoadFileAndRecord : GameBP.PaperAI.BehaviourTree.BTT.BTT_WorldAI_CastSkill_C
[2024.01.17-15.20.33:309][452]LogUnLua: UNLUA_PRINT[6517] : GameBP/PaperAI/BehaviourTree/BTT/BTT_WorldAI_CastSkill_C.lua
[2024.01.17-15.20.33:310][452]LogUnLua: UNLUA_PRINT[6517] : SelfLoadFileAndRecord : GameBP.PaperAI.BehaviourTree.BTT.BTT_WorldAI_PlayEnterBattleAnim_C
[2024.01.17-15.20.33:310][452]LogUnLua: UNLUA_PRINT[6517] : GameBP/PaperAI/BehaviourTree/BTT/BTT_WorldAI_PlayEnterBattleAnim_C.lua
[2024.01.17-15.20.33:310][452]LogUnLua: UNLUA_PRINT[6517] : daxu EntityHelper SnapActorToFloor name:BP_CombatWorldMonster_V2_KaiJia_C@0@562949953423367@3
[2024.01.17-15.20.33:311][452]LogUnLua: [LUA][15:20:33:311][6452][EntityModule:477]:[__PopSpawnEntitiesAndSpawntoWorld] SpawnActorToWorld BP_CombatWorldMonster_V2_KaiJia_C@0@562949953423367@3 cost: 34 ms
[2024.01.17-15.20.33:322][453]LogUnLua: UNLUA_PRINT[6518] : SelfLoadFileAndRecord : GameBP.PaperAI.AgentTask.TaskImpl.BP_AgentTask_Birth_C
[2024.01.17-15.20.33:322][453]LogUnLua: UNLUA_PRINT[6518] : GameBP/PaperAI/AgentTask/TaskImpl/BP_AgentTask_Birth_C.lua
[2024.01.17-15.20.33:323][453]LogUnLua: UNLUA_PRINT[6518] : SelfLoadFileAndRecord : GameBP.PaperAI.AgentTask.BP_AgentTaskBase_C
[2024.01.17-15.20.33:323][453]LogUnLua: UNLUA_PRINT[6518] : GameBP/PaperAI/AgentTask/BP_AgentTaskBase_C.lua
[2024.01.17-15.20.33:329][453]LogUnLua: UNLUA_PRINT[6518] : SelfLoadFileAndRecord : GameBP.PaperAI.StateManagement.FSM_WorldAI_Default_C
- 跟踪SkeletMesh的Tick逻辑,发现有个URO设置可以减少Tick的频率,中间可以通过插值近似,验证也确实效率提高不少。后和feige沟通,这个之前是因为一些表现效果达不到而没开启。
- Profile Lua开销,还是准备尝试下预载入Lua文件。
- 帮助Review下gufeng的堆栈平衡修改。
NOPRELOAD
PRELOAD
↩︎