UE4 對象類型Class及內存管理(1)

UE4中的對象在內存中的表示目前大概可分為三類:·

A、普通的C++類型 F Class

B、智能指針

C、UObject類型的UClass

我們逐一說明他們的使用方法和注意事項

1、針對普通的C++的class照普通的使用方式即可;UED中或者UE4的底層很多使用這種Class的例子;但UE4會統一的在前加F 比如:上次我們說的負責坐標軸繪製和處理的FWidget類(在UnrealWidget.h中)

聲明:

class FWidgetnt: public FGCObjectn{nFWidget();n}n

使用:

FEditorViewportClient::FEditorViewportClient(FEditorModeTools* InModeTools, FPreviewScene* InPreviewScene, const TWeakPtr<SEditorViewport>& InEditorViewportWidget)nt: bAllowCinematicPreview(false)n...n, Widget(new FWidget)n

銷毀:

FEditorViewportClient::~FEditorViewportClient()n{nt...ntdelete Widget;n}n

目前大部分的F Class都在UED的框架中使用。在game的框架中相同功能的Class都改成了UClass

2、UE4的智能指針SmartPointer體系在引擎初期項目中用處主要在UI上;SlateUI是主要使用智能指針的地方。但隨著後期UMG的出現SlateUI的部分被完全封裝在UMG內部,現在研發人員一般不會接觸到這一塊。但對於研究引擎的人來說熟悉智能指針相當重要。以SWidget為例說明

聲明方式():

class SLATECORE_API SWidgetnt: public FSlateControlledConstruction,nt public TSharedFromThis<SWidget>tt// Enables this->AsShared()n{ntfriend struct FCurveSequence;nt//dubeibei XModntfriend class UXScriptWidget;npublic:n}n

重點是類模版TSharedFromThis<SWidget>;TSharedPtr<>;TSharedRef<>

template< class ObjectType, ESPMode Mode >nclass TSharedFromThisn{};nntemplate< class ObjectType, ESPMode Mode >nclass TSharedPtrn{};n

template< class ObjectType, ESPMode Mode >

class TSharedRef

{};

template< class ObjectType, ESPMode Mode >

class TWeakPtr

{

public:

};

詳情見:SharedPointer.h 其中指針會有SharedReferenceCount保存計數;計數為0時自動清理。TWeakPtr中有WeakReferenceCount保存計數,但TWeakPtr的引用計數不作為是否清理的標記,即TweakPtr中的Object可能已經被清理;但TweakPtr還在;可使用TWeakPtr的Isvalid來校驗Object是否已被清理。

使用方式:

TSharedPtr<SWidget> RetWidget = SNew(SInvalidationPanel)n

或者:

SAssignNew(MyTextBlock, STextBlock)n

或者:

MakeShareable(new FUIController()); 返回的也是一個TSharedPtrn

關於TSharedPtr TSharedRef TWeakPtr之間相互轉換的使用:

TSharedPtr ToSharedRef()-> TSharedRef

TWeakPtr Pin()-> TSharedPtr

TSharedRef

轉換使用StaticCastSharedPtr:

TSharedPtr<SChannelListPageWidget> MyWidget = StaticCastSharedPtr<SChannelListPageWidget>(GetWidget());n

3、關於 UObject的Class使用

UObject是上層或者Game框架裡面最經常用到的Class。把遊戲框架中出現的各種東西抽象出一個UObject十分必要;通用的屬性和介面;統一的GC;方便數據統計;等等

聲明示例如下:

UCLASS(config = Game, meta = (ChildCanTick))nclass PROJECTZ_API AMaterialParamaterObject : public AActorn{ntGENERATED_UCLASS_BODY()nnt/** The CapsuleComponent being used for movement collision (by CharacterMovement). Always treated as being vertically aligned in simple collision check functions. */ntUPROPERTY(Category = Character, VisibleAnywhere, BlueprintReadOnly)ntclass USceneComponent* RootSceneCom;nnt/** The main skeletal mesh associated with this Character (optional sub-object). */ntUPROPERTY(Category = MapEditor, VisibleAnywhere, BlueprintReadOnly)ntclass UStaticMeshComponent* Mesh;nntstatic FName MeshComponentName;ntstatic FName RootComponentName;nntUFUNCTION(BlueprintCallable, Category = "MapEditor|Objects")ntvoid ChangeFloatParamater(int32 ParaIndex, int32 NameIndex, float InValue);nntUFUNCTION(BlueprintCallable, Category = "MapEditor|Objects")ntvoid ChangeIntParamater(int32 ParaIndex, int32 NameIndex, int32 InValue);nntUFUNCTION(BlueprintCallable, Category = "MapEditor|Objects")ntvoid ChangeVectorParamater(int32 ParaIndex, int32 NameIndex, FVector InValue);nntUFUNCTION(BlueprintCallable, Category = "MapEditor|Objects")ntvoid ChangeTextureParamater(int32 ParaIndex, int32 NameIndex, UTexture2D* InValue);nntUPROPERTY(Category = "MapEditor|Objects", EditAnywhere, BlueprintReadWrite)ntTArray<FEditorMaterialParamater> Paramaters;nn};n

關於UHT:UnrealHeaderTool,UHT會根據UClass的頭文件.h生成.generated.h文件把其中擁有UPROPERTY UFUNCTION的標籤的重新定義例如ChangeFloatParamater介面:

DECLARE_FUNCTION(execChangeFloatParamater) nt{ nttP_GET_PROPERTY(UIntProperty,Z_Param_ParaIndex); nttP_GET_PROPERTY(UIntProperty,Z_Param_NameIndex); nttP_GET_PROPERTY(UFloatProperty,Z_Param_InValue); nttP_FINISH; nttP_NATIVE_BEGIN; nttthis->ChangeFloatParamater(Z_Param_ParaIndex,Z_Param_NameIndex,Z_Param_InValue); nttP_NATIVE_END; nnt}n

新生成的.genreated.h文件會加入編譯所有的UPROPERTY和UFUNCTION都會是繼承自UObject的Class使用 ;然後再由GC統一的管理UObject;

不加UPROPETY標籤的屬性不在UObject 此過程GC的範圍之內;需要另外的控制,不然很容易內存泄漏。見下章詳細說明。

使用:

MyGCProtectedObj = NewObject<UMyObjectClass>(this);

如果不想讓UObject強制回收可設置:

YourObjectInstance->AddToRoot();

銷毀:

if(!MyObject) return;nif(!MyObject->IsValidLowLevel()) return;n nMyObject->ConditionalBeginDestroy(); //instantly clears UObject out of memorynMyObject = nullptr;nn銷毀Actor:nif(!TheCharacter) return;nif(!TheCharacter->IsValidLowLevel()) return;nTheCharacter->Destroy();nTheCharacter->ConditionalBeginDestroy(); //essential extra step, in all my testingn

參考:

Unreal Object Handling

Garbage Collection & Dynamic Memory Allocation

Unreal Smart Pointer Library

推薦閱讀:

非同步操作時的內存管理?
Python可以視作同時支持像C++一樣的RAII特性,也具有垃圾回收GC的編程語言嗎?
linux怎麼管理空閑內存?
80386的頁式內存管理
浪費內存?多大個事?

TAG:虚幻4游戏引擎 | 内存管理 | 类与对象 |