【UE4 C++】UObject 创建、销毁、内存管理

UObject 的创建

NewObject 模板类

  • 本例使用 UE 4.26,只剩下 NewObject 用来创建 UObject,提供两个带不同可选参数构造函数的模板类

  • Outer 表示这个对象的外部对象,通常可传 this 指针进去

  • Name 为对象名,如果没有自定义,默认生成,自带 GetName() 方法获取

    template<class T>
    T* NewObject(UObject* Outer)
    {
    	T* Object = ::NewObject<T>(Outer);
    	Object->SetInternalFlags(EInternalObjectFlags::Async);
    	return Object;
    }
    
    template<class T>
    T* NewObject(UObject* Outer, UClass* Class, FName Name = NAME_None, 
    	EObjectFlags Flags = RF_NoFlags, UObject* Template = nullptr,
    	bool bCopyTransientsFromClassDefaults = false, FObjectInstancingGraph* InInstanceGraph = nullptr)
    {
    	T* Object = ::NewObject<T>(Outer, Class, Name, Flags, Template, bCopyTransientsFromClassDefaults, InInstanceGraph);
    	Object->SetInternalFlags(EInternalObjectFlags::Async);
    	return Object;
    }
    

实践

  • 创建一个 UObject 类

    UCLASS()
    class TIPS_API UItemObject : public UObject
    {
    	GENERATED_BODY()
    	FString m_Name;
    public:
    	UItemObject() { 
    		m_Name = GetName();
    		UE_LOG(LogTemp, Warning, TEXT(__FUNCTION__" %s"), *m_Name);
    	}
    
    	~UItemObject() { UE_LOG(LogTemp, Warning, TEXT(__FUNCTION__" %s"), *m_Name); }
    };
    
  • 创建 UObject 实例

    UItemObject* Obj = NewObject<UItemObject>();
    UItemObject* Obj2 = NewObject<UItemObject>(this, TEXT("Obj2"));
    

UObject 的销毁

自动销毁

  • UObject及其派生 具有被 UE4 垃圾回收机制管理,因而当指向对象的指针为 nullptr 后,将会被 UE4 自动回收掉

    Obj = NewObject<UItemObject>(this, TEXT("Obj"));
    Obj = nullptr;
    

主动销毁

  • UObject::ConditionalBeginDestroy()

    • 异步执行且对象在当前帧内持续有效
    • 等待下次GC
    Obj->ConditionalBeginDestroy();
    Obj = nullptr;
    
  • MarkPendingKill()

    • 标记为PendingKill,等待回收。指向此实例的指针将设置为NULL,并在下一次GC时删除。
    • IsPendingKill 判断是否处于 PendingKill 状态
    • ClearPendingKill 清除 PendingKill 状态
    Obj->MarkPendingKill();
    Obj = nullptr;
    
  • Engine\Config \BaseEngine.ini 更改下面参数,设置销毁时间间隔

    gc.TimeBetweenPurgingPendingKillObjects=60
    

强制垃圾回收

  • UWorld::ForceGarbageCollection 弃用

  • GEngine->ForceGarbageCollection

    GEngine->ForceGarbageCollection(true);
    

原生对象内存管理

new/delete

  • 需要手动清理,易造成内存泄漏

  • delete 一般将指针置为 nullptr ,防止指向的地址不固定

    class SimpleObject {
    public:
    	SimpleObject() { UE_LOG(LogTemp, Warning, TEXT(__FUNCTION__)); }
    	~SimpleObject() { UE_LOG(LogTemp, Warning, TEXT(__FUNCTION__)); }
    };
    
    SimpleObject* Obj = new SimpleObject();
    
    delete Obj;
    Obj = nullptr;
    

    image

使用智能指针

  • 对于非 UObject 的对象,可以使用智能指针进行管理
  • 当引用计数为0时,对象自动销毁

UObject 对象内存管理

UPROPERTY() 保持引用

  • 支持容器 TArray、TMap 的 <UObject*>类型。TArray、TMap使用UPROPERTY() ,也可以使元素对象常驻内存

    UPROPERTY()
    	class UItemObject* m_ItemObject2;
    
    UPROPERTY()
    	TArray<class UItemObject*> m_ObjList1;
    

AddToRoot 和 RemoveFromRoot 标记不被GC/移除标记

  • 构造时 和 AddToRoot 一起

  • 析构时和 RemveFromRoot 一起

    //创建对象
    m_ItemObject1 = NewObject<UItemObject>(this,TEXT("m_ItemObject1"));
    m_ItemObject1->AddToRoot();
    
    // 释放对象
    m_ItemObject1->RemoveFromRoot();
    m_ItemObject1 = nullptr;
    

    image

FStreamableManager 资源卸载

  • FStreamableHandle::ReleaseHandle()

    TSharedPtr<FStreamableHandle> Handle  = UAssetManager::GetStreamableManager().RequestSyncLoad(AssetPath);
    UObject* Obj = Handle->GetLoadedAsset();
    Handle->ReleaseHandle();
    

AActor 销毁

  • Destroy() 方法

UActorComponent

  • DestroyComponent() 方法

扩展:FGCObjectScopeGuard

posted @ 2021-05-05 13:04  砥才人  阅读(9542)  评论(1编辑  收藏  举报