Bootstrap

虚幻四源码阅读UObjectBase,UObjectBaseUtility,UObjectBase

新手,有错请指出,大家共同进步

Object

UObjectBase

说明

Unreal中UObject的基类

属性

类型 名字 说明
EObjectFlags ObjectFlags ObjectFlags是用于跟踪和记录对象的各种状态,它被引擎用于表示对象加载、保存、编辑、垃圾回收和对象作用标识时候使用。简单地说,就是一个标记信息。
int32 InternalIndex 全局对象数组的下标,unreal在运行时候会维护一个全局的对象数组,每当创建一个对象的时候便放到数组里面
UClass* ClassPrivate 类型信息
FName NamePrivate 对象名字
UObject* OuterPrivate Outer对象的指针,暂时没弄明白是啥意思。(update)一个对象A的"Outer"是拥有A的对象。例如,Component由其Actor或父组件拥有,Actors由其Levels拥有。 无论何时构造从UObject派生的类的对象,都要为它提供外部。 (CreateDefaultSubobject隐式提供当前对象作为外部。)可不可以这样说,人是一个对象,手是一个对象,而手的outer是人? 看这里解释

构造函数

UObjectBase

()

这个构造函数,只把NamePrivate设置为NoInit,其他啥事都没有做

UObjectBase

( EObjectFlags InFlags )

Constructor used for bootstrapping

这时候对象并没有加入到全局对象数组中,感觉有特殊用途

UObjectBase

(UClass* InClass, EObjectFlags InFlags, EInternalObjectFlags InInternalFlags, UObject *InOuter, FName InName)

UObjectBase::UObjectBase(UClass* InClass, EObjectFlags InFlags, EInternalObjectFlags InInternalFlags, UObject *InOuter, FName InName)
:	ObjectFlags			(InFlags)
,	InternalIndex		(INDEX_NONE)
,	ClassPrivate		(InClass)
,	OuterPrivate		(InOuter)
#if ENABLE_STATNAMEDEVENTS_UOBJECT
, StatIDStringStorage(nullptr)
#endif
{
	check(ClassPrivate);
	// Add to global table.
	AddObject(InName, InInternalFlags);
}

这个构造函数是用于创建静态分配的对象,应该是一般的对象,构造函数把属性都赋值了,但是值得注意的是,InternalIndex的值为INDEX_NONE,也就是-1,并没有马上就把对象加入了全局对象数组中。是不是说,创建该对象前,不能知道InternalIndex? EInternalObjectFlags标记存放在全局对象管理数组的元素中(这是为了提高Cache命中率)

后面调用check(ClassPrivate)来判断classPrivate是否为NULL

最后AddObject(InName, InInternalFlags)把对象加入到全局对象数组中

析构函数

~UObjectBase()

/**
 * Final destructor, removes the object from the object array, and indirectly, from any annotations
 **/
UObjectBase::~UObjectBase()
{
	// If not initialized, skip out.
	if( UObjectInitialized() && ClassPrivate && !GIsCriticalError )
	{
		// Validate it.
		check(IsValidLowLevel());
		LowLevelRename(NAME_None);
		GUObjectArray.FreeUObjectIndex(this);
	}

#if ENABLE_STATNAMEDEVENTS_UOBJECT
	delete[] StatIDStringStorage;
	StatIDStringStorage = nullptr;
#endif
}

通过LowLevelRename(NAME_None)改掉名字,通过GUObjectArray.FreeUObjectIndex(this)把对象从全局对象数组中去掉

函数

void AtomicallyClearFlags

(EObjectFlags FlagsToClear)

/**
 *	Atomically clears the specified flags.
 *	Do not use unless you know what you are doing.
 *	Designed to be used only by parallel GC and UObject loading thread.
 */
FORCENOINLINE void AtomicallyClearFlags( EObjectFlags FlagsToClear )
{
	int32 OldFlags = 0;
	int32 NewFlags = 0;
	do 
	{
		OldFlags = ObjectFlags;
		NewFlags = OldFlags & ~FlagsToClear;
	}
	while( FPlatformAtomics::InterlockedCompareExchange( (int32*)&ObjectFlags, NewFlags, OldFlags) != OldFlags );
}

原子级别上清理flags,是不是能理解成在flags上的位上进行清理操作呢?为什么要这样操作?

void AtomicallySetFlags

(EObjectFlags FlagsToAdd)

/**
 *	Atomically adds the specified flags.
 *	Do not use unless you know what you are doing.
 *	Designed to be used only by parallel GC and UObject loading thread.
 */
FORCENOINLINE void AtomicallySetFlags( EObjectFlags FlagsToAdd )
{
	int32 OldFlags = 0;
	int32 NewFlags = 0;
	do 
	{
		OldFlags = ObjectFlags;
		NewFlags = OldFlags | FlagsToAdd;
	}
	while( FPlatformAtomics::InterlockedCompareExchange( (int32*)&ObjectFlags, NewFlags, OldFlags) != OldFlags );
}

原子级别上清理flags,***是不是能理解成在flags上的位上进行清理操作呢?***为什么要这样操作?

void DeferredRegister

(
UClass * UClassStaticClass,
const TCHAR * PackageName,
const TCHAR * Name
)

/**
 * Convert a boot-strap registered class into a real one, add to uobject array, etc
 *
 * @param UClassStaticClass Now that it is known, fill in UClass::StaticClass() as the class
 */
void UObjectBase::DeferredRegister(UClass *UClassStaticClass,const TCHAR* PackageName,const TCHAR* InName)
{
    //检查该对象是否已经初始化,当UObjectBaseInit()调用后,就初始化了。
	check(Internal::GObjInitialized);
	// Set object properties.
    
    //根据PackageName找到Outer,然后设置本对象的Outer
	UPackage* Package = CreatePackage(nullptr, PackageName);
	check(Package);
	Package->SetPackageFlags(PKG_CompiledIn);
	OuterPrivate = Package;

	ch
;