首先,蓝图调用实在CPP调用之后执行。
模块加载时候回调用所有的UClass的CreateDefaultObject函数,产生默认的OBJECT,以后拷贝默认的就行了
在任何一个Actor构造函数里面打断点,然后play
UnrealEngine\Engine\Source\Runtime\CoreUObject\Private\UObject\UObjectGlobals.cpp
UObject* StaticConstructObject_Internal ( UClass* InClass, UObject* InOuter /*=GetTransientPackage()*/, FName InName /*=NAME_None*/, EObjectFlags InFlags /*=0*/, EInternalObjectFlags InternalSetFlags /*=0*/, UObject* InTemplate /*=NULL*/, bool bCopyTransientsFromClassDefaults /*=false*/, FObjectInstancingGraph* InInstanceGraph /*=NULL*/ ) { SCOPE_CYCLE_COUNTER(STAT_ConstructObject); UObject* Result = NULL; #if WITH_EDITORONLY_DATA UE_CLOG(GIsSavingPackage && InOuter != GetTransientPackage(), LogUObjectGlobals, Fatal, TEXT("Illegal call to StaticConstructObject() while serializing object data! (Object will not be saved!)")); #endif checkf(!InTemplate || InTemplate->IsA(InClass) || (InFlags & RF_ClassDefaultObject), TEXT("StaticConstructObject %s is not an instance of class %s and it is not a CDO."), *GetFullNameSafe(InTemplate), *GetFullNameSafe(InClass)); // template must be an instance of the class we are creating, except CDOs // Subobjects are always created in the constructor, no need to re-create them unless their archetype != CDO or they're blueprint generated. // If the existing subobject is to be re-used it can't have BeginDestroy called on it so we need to pass this information to StaticAllocateObject. const bool bIsNativeClass = InClass->HasAnyClassFlags(CLASS_Native | CLASS_Intrinsic); const bool bIsNativeFromCDO = bIsNativeClass && ( !InTemplate || (InName != NAME_None && InTemplate == UObject::GetArchetypeFromRequiredInfo(InClass, InOuter, InName, InFlags)) ); #if WITH_HOT_RELOAD // Do not recycle subobjects when performing hot-reload as they may contain old property values. const bool bCanRecycleSubobjects = bIsNativeFromCDO && !GIsHotReload; #else const bool bCanRecycleSubobjects = bIsNativeFromCDO; #endif bool bRecycledSubobject = false; Result = StaticAllocateObject(InClass, InOuter, InName, InFlags, InternalSetFlags, bCanRecycleSubobjects, &bRecycledSubobject); check(Result != NULL); // Don't call the constructor on recycled subobjects, they haven't been destroyed. if (!bRecycledSubobject) { FScopeCycleCounterUObject ConstructorScope(InClass, GET_STATID(STAT_ConstructObject)); (*InClass->ClassConstructor)( FObjectInitializer(Result, InTemplate, bCopyTransientsFromClassDefaults, true, InInstanceGraph) ); } if( GIsEditor && GUndo && (InFlags & RF_Transactional) && !(InFlags & RF_NeedLoad) && !InClass->IsChildOf(UField::StaticClass()) ) { // Set RF_PendingKill and update the undo buffer so an undo operation will set RF_PendingKill on the newly constructed object. Result->MarkPendingKill(); SaveToTransactionBuffer(Result, false); Result->ClearPendingKill(); } return Result; }
Result = StaticAllocateObject(InClass, InOuter, InName, InFlags, InternalSetFlags, bCanRecycleSubobjects, &bRecycledSubobject);
上面这一行分配内存
(*InClass->ClassConstructor)( FObjectInitializer(Result, InTemplate, bCopyTransientsFromClassDefaults, true, InInstanceGraph) );
上面这一行调用构造函数,我猜应该是先把上面构造那个默认的给拷贝过来,然后再调用下面的初始化函数。
参数类型为FObjectInitializer的构造函数是在自动生成的generate.h文件中声明的,类似于这样,我的这个类名是AGame1Character
#define Game1_Source_Game1_Game1Character_h_9_STANDARD_CONSTRUCTORS \ /** Standard constructor, called after all reflected properties have been initialized */ \ NO_API AGame1Character(const FObjectInitializer& ObjectInitializer); \ DEFINE_DEFAULT_OBJECT_INITIALIZER_CONSTRUCTOR_CALL(AGame1Character) \ DECLARE_VTABLE_PTR_HELPER_CTOR(NO_API, AGame1Character); \ DEFINE_VTABLE_PTR_HELPER_CTOR_CALLER(AGame1Character); \DEFINE_DEFAULT_OBJECT_INITIALIZER_CONSTRUCTOR_CALL这个宏是这样
#define DEFINE_DEFAULT_OBJECT_INITIALIZER_CONSTRUCTOR_CALL(TClass) \ static void __DefaultConstructor(const FObjectInitializer& X) { new((EInternal*)X.GetObj())TClass(X);
enum EInternal {EC_InternalUseOnlyConstructor};
placement new 直接在返回的object指针位置调用了构造函数。然后就调到我们写的构造函数,(上面那个还有个无参数版本,类似于 TClass())
引擎一开始先开辟一个数组,存放所有的活着的UOBJECT。其实就是个Object的指针和这个object的flag。
maloc其实就是单纯的开辟内存,目前没有发现内存池在哪里。在我的PC上是英特尔的TBB算法(TBB(intel threading building blocks)内存分配算法)。
Engine_Updating\Engine\Source\Runtime\CoreUObject\Private\UObject\UObjectArray.cpp
void FUObjectArray::AllocateObjectPool(int32 InMaxUObjects, int32 InMaxObjectsNotConsideredByGC) { check(IsInGameThread()); MaxObjectsNotConsideredByGC = InMaxObjectsNotConsideredByGC; // GObjFirstGCIndex is the index at which the garbage collector will start for the mark phase. // If disregard for GC is enabled this will be set to an invalid value so that later we // know if disregard for GC pool has already been closed (at least once) ObjFirstGCIndex = DisregardForGCEnabled() ? -1 : 0; // Pre-size array. check(ObjObjects.Num() == 0); UE_CLOG(InMaxUObjects <= 0, LogUObjectArray, Fatal, TEXT("Max UObject count is invalid. It must be a number that is greater than 0.")); ObjObjects.PreAllocate(InMaxUObjects); if (MaxObjectsNotConsideredByGC > 0) { ObjObjects.AddRange(MaxObjectsNotConsideredByGC); } }