UE4學習(一)C++編程官方文檔解讀

文檔地址:https://docs.unrealengine.com/zh-CN/Programming/Introduction/index.html

文檔詳細介紹了C++編程的基礎,一些宏和常用變量,做下總結

(一)文檔一開始介紹了Actor繼承類編程的一些相關知識,以及一些有關UPROPERTY和UFUNCTION相關的簡單介紹,之後簡單介紹了藍圖。

(二)之後就是深入介紹

主要的類是四種,UObject,AActor,UActorComponnnet,UStruct。

(1)UObject是最基本的構建塊,結合UClass可以提供反射、序列化、垃圾回收、聯網。每個UObject都會創建一個UClass。我的理解是,UClass對UObject的梳理進行管理,並且提供序列化和聯網等功能。

(2)AActor是非常重要的一種類型,可以直接放在舞臺上的所有對象都是從其擴展而來,AActor繼承自UObject,同時AActor有一些特殊的函數,BeginPlay()在對象首次存在是調用,Tick()每幀調用一次,EndPlay()在對象離開Gameplay空間時調用。

UWorld::SpawnActor()。成功產生Actor後,會調用它的 BeginPlay() 方法,下一幀調用 Tick()

使用時使用GetWorld()->SpawnActor<T>(),使用這個函數偶爾會出現編輯器崩潰,以後需要關注類似問題。

(3)UActorComponent

(4)UStruct,不會被垃圾回收

(三)虛幻反射系統

GamePlay類利用特殊標記實現反射功能,反射功能可以實現動態功能,例如GC、序列化、網絡複製和BP/C++通信。簡要標記概述:

UCLASS():爲結構體生成反射數據,結構體必須派生自UObject

USTRUCT()生成反射,不需要派生自UObject

GENERATED_BODY()UE4替換爲相關的生成代碼

UPROPERTY:變量

UFUNCTION:方法

示例

#include "MyObject.generated.h"

UCLASS(Blueprintable)
class UMyObject : public UObject
{
    GENERATED_BODY()

public:
    MyUObject();

    UPROPERTY(BlueprintReadOnly, EditAnywhere)
    float ExampleProperty;

    UFUNCTION(BlueprintCallable)
    void ExampleFunction();
};
  • Blueprintable - 該類可以由藍圖擴展。

  • BlueprintReadOnly - 該屬性可以從藍圖讀取,但不能寫入藍圖。

  • EditAnywhere - 該屬性可以在原型和實例上的屬性窗口中編輯。

  • Category - 定義該屬性將出現在編輯器“細節(Details)”視圖下面的哪個部分。這對於整理結構而言十分有用。

  • BlueprintCallable - 該功能可以從藍圖調用。

(四)迭代器介紹

對象迭代器:迭代特定類型的UObject及其子類

// 查找所有當前UObject實例,不包括子類
for (TObjectIterator<UObject> It; It; ++It)
{
    UObject* CurrentObject = *It;
    UE_LOG(LogTemp, Log, TEXT("Found UObject named:%s"), *CurrentObject->GetName());
}
//包括子類
for (TObjectIterator<UMyClass> It; It; ++It)
{
    // ...
}

AActor也有自己的迭代器,

APlayerController* MyPC = GetMyPlayerControllerFromSomewhere();
UWorld* World = MyPC->GetWorld();

// 正如對象迭代器一樣,您可以提供一個具體類來僅獲得
// 屬於該類或派生自該類的對象
for (TActorIterator<AEnemy> It(World); It; ++It)
{
    // ...
}

 使用Actor迭代器需要World,上述提供了一個獲取World的方法。

 

(五)垃圾回收

UE4使用反射系統實現垃圾回收,繼承自UObject的物體會實現自動垃圾回收,當沒有有效引用的時候會實現垃圾回收。

void CreateDoomedObject()
{
    MyGCType* DoomedObject = NewObject<MyGCType>();
}

函數運行完成之後臨時變量無引用,會在下一次垃圾清理的時候觸發GC。

AActor只有在手動調用Destroy函數時纔會在下一次GC時被銷燬。

UStruct不參與GC。

繼承FGCObject參與GC。

 

(六)字符串

FString類型字符串需要TEXT()宏創建。用途類似於std::String

FText使用NSLOCTEXT創建

FName使用字典處理,速度較快

 (七)容器

主要包括TArray、TMap、TSet

TArray類似vector,TMap是鍵值對的集合,TSet是唯一值集合。

容器迭代器:

void RemoveDeadEnemies(TSet<AEnemy*>& EnemySet)
{
    // 從集開頭處開始,迭代至集末尾
    for (auto EnemyIterator = EnemySet.CreateIterator(); EnemyIterator; ++EnemyIterator)
    {
        // *運算符獲取當前元素
        AEnemy* Enemy = *EnemyIterator;
        if (Enemy.Health == 0)
        {
            //“RemoveCurrent”受TSet和TMap支持
            EnemyIterator.RemoveCurrent();
        }
    }
}

// 將迭代器向後移動一個元素
--EnemyIterator;

// 將迭代器向前/向後移動一定偏移量,這裏的偏移量是個整數
EnemyIterator += Offset;
EnemyIterator -= Offset;

// 獲取當前元素的索引
int32 Index = EnemyIterator.GetIndex();

// 將迭代器復位到第一個元素
EnemyIterator.Reset();

 還可以使用foreach循環

// TArray
TArray<AActor*> ActorArray = GetArrayFromSomewhere();
for (AActor* OneActor :ActorArray)
{
    // ...
}

// TSet——與TArray相同
TSet<AActor*> ActorSet = GetSetFromSomewhere();
for (AActor* UniqueActor :ActorSet)
{
    // ...
}

// TMap——迭代器返回鍵-值對
TMap<FName, AActor*> NameToActorMap = GetMapFromSomewhere();
for (auto& KVP :NameToActorMap)
{
    FName Name = KVP.Key;
    AActor* Actor = KVP.Value;

    // ...
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章