Aery的UE4 C++游戲開發之旅(1)基礎對象模型


引擎版本:Unreal Engine 4.22

UObject

UE4的最基礎類型是UObject,它提供了如下功能:

  • GC機制(垃圾回收機制)
  • 引用自動更新
  • 運行時類型識別
  • 反射機制
  • 序列化
  • 自動檢測默認變量的變更
  • 屬性自動初始化
  • UE4編輯器的自動整合
  • 網絡復制
  • ...

這樣當我們編寫需要使用以上功能的類時,繼承一下UObject即可。
后面要講的Actor和Component便是這樣做的。

更多功能或細節,可參考源文件Engine\Source\Runtime\CoreUObject\Public\UObject\Object.h

Actor種類

每個游戲引擎都會有一個非常重要的游戲對象類型,在cocos2d-x里是Node(節點),在Unity3D里是GameObject(游戲對象),而在UE4里,這個重要的角色則是Actor(演員)。

可能在UE4引擎設計者的眼里,游戲世界是一個舞台,把各個Actor放置在舞台上面,便能展現出一出好戲。

在UE編輯器的World Outliner窗口可以看到當前場景的所有Actor實例:

AActor

AActor類是可以放到游戲場景中的游戲對象的基本類型,另外它更強大的能力是可以掛載組件(Component)。
組件提供功能,想讓一個實體Actor擁有更多的功能就可以通過掛載不同的組件實現。

可以看到AActor繼承於UObject,然后再派生出各式各樣的Actor類(例如APawn)。這是因為舞台需要放置各式各樣的演員,而在UE4的世界觀里,演員不僅包含游戲世界里的角色、NPC、載具,還可以是一間房子、一把武器、一個掉落的蘋果,甚至一個抽象的游戲規則、看不見的玩家控制器...

你如果想放置任何有實質作用的東西到游戲場景中,應該繼承AActor類。

APawn(可操控單位)

簡單來說,APawn類是一個代表可被控制的游戲對象(玩家角色、怪物、NPC、載具等),它繼承於AActor。
對於開發者,每次創建Pawn都得從Pawn類繼承,然后寫各種各樣的實現/添加各種各樣的組件。
於是UE4提供了幾個派生類作為模板,以便快速編寫自己的Pawn。

  • ADefaultPawn (默認的可操控單位)

    DefaultPawn繼承於APawn,是一個默認的Pawn模板。它默認帶了一個DefaultPawnMovementComponent、SphericalCollisionComponent和StaticMeshComponent。

  • ASpectatorPawn(觀察者)

    SpectatorPawn繼承於APawn,是適用於觀戰的Pawn模板,擁有攝像機“漫游”的能力。它實際就是提供了一個基本的USpectatorPawnMovement(不帶重力漫游),並關閉了StaticMesh的顯示,碰撞也設置到了“Spectator”通道。

  • ACharacter(角色)

    Character繼承於APawn,是一個包含了行走,跑步,跳躍以及更多動作的Pawn模板。它含有像人一樣行走的CharacterMovementComponent,盡量貼合的CapsuleComponent,再加上骨骼上蒙皮的網格。

AController(控制器)

AController繼承於AActor,Controller通過接受玩家的設備(鍵盤、鼠標等)輸入或者被AI輸入來控制Pawn。實際上一個Pawn可以被多個Controller操控(例如載具可由一個玩家駕駛,另一個玩家操控車頂機槍),也可以切換Controller(例如,完成一段劇本演出時,玩家不能控制主角,而交由劇本腳本控制。)

  • APlayerController(玩家控制器)

    APlayerController繼承於AController,負責接受玩家設備輸入從而控制Pawn,它提供了Camera(控制玩家視角)、設備輸入處理、關聯UPlayer、顯示HUD等功能、切換Level...

  • AAIController(AI控制器)

    AAIController繼承於AController,負責提供AI從而控制Pawn,它提供了導航網格尋路、AI行為樹、Task系統...

AGameMode(游戲模式)

AGameMode繼承於AActor,這是一個很重要的類。因為一個GameMode定義了游戲的規則(例如如何得分或者其他方面的系統邏輯內容),我們經常需要繼承於它編寫自己游戲的全局規則/全局游戲邏輯。
由於游戲邏輯規則往往是單例的,我們可以通過UGameplayStatics::GetGameMode這個靜態函數來獲取GameMode的實例:

   AMyGameMode* MyGameMode;
   //得到自己定義的AMyGameMode實例
   MyGameMode = Cast<AMyGameMode>(UGameplayStatics::GetGameMode(this));

此外GameMode默認是不打開每幀調用Tick事件的,這里我就被坑了下。

AHUD(HUD)

AHUD繼承於AActor,它是平面顯示界面,就是平時我們玩3D游戲提供給玩家的2D菜單界面。AHUD類提供了渲染文字、貼圖、矩形和材質的渲染,創建后也可以通過藍圖來編輯界面。

...

Component種類

隨意點擊一個Actor,可以查看該Actor的所有Component(組件):

UActorComponent(基本組件)

UActorComponent繼承於UObject,是最基本的組件類型。不過需要注意的是,它沒有Transform,也沒有提供嵌套包含其他Actor組件的功能。
這是因為在UE看來,Actor並不只是3D世界中的表示,一些不在世界中展示的“不可見對象”也可以是Actor,比如AInfo等,所以這些Actor的組件也就沒有自帶Transform了。

USceneComponent(場景組件)

繼承於UActorComponent,它封裝了Transform來表示其位置。所以需要位置表示的Actor就可以向Actor中添加SceneComponent作為其RootComponent(例如APawn就自動創建了SceneComponent)。
與此同時,得益於Transform(可以計算相對位置),SceneComponent可以允許嵌套包含其他Actor組件(例如一個人體組件包含身體組件,一個身體組件又可以包含手組件)。

實際中大部分的Actor是有Transform的,所以我們會經常設置獲取它的坐標。常理來說,我們的需要先獲取下SceneComponent,然后才能操作其Transform等相應接口。但是這樣太過繁瑣,因此UE為我們直接提供了基於Actor的接口,如(Get/Set)ActorLocation,但其實這些接口內部也是轉發到RootComponent的。
同理,Actor能接收處理Input事件的能力,其實也是轉發到Actor內部的UInputComponent* InputComponent;

UChildActorComponent(子演員組件)

繼承於USceneComponent,提供了Component之下再疊加Actor的能力,擔負着Actor之間互相組合的膠水。這貨在藍圖里靜態存在的時候其實並不真正的創建Actor,而是在之后Component實例化的時候才真正創建。

UStaticMeshComponent(靜態網格組件)

繼承於USceneComponent,是一個靜態網格組件,也就是提供一個靜態網格物體的渲染效果/物理碰撞等。

...

總結

實際上,UE4的Actor-Component系統就與Unity3D的GameObject-Component系統很相似。
一個游戲場景里擺放若干個演員(Actor),每個演員雖然空無一物(沒穿衣服),但是可以通過給它添加不同的服飾、台詞等(Component)從而展現出很多不同的性質,從而呈現出一款精彩的游戲舞劇。

而Actor的各種派生類實際上只是Acotr加上提前准備好這些特定的服飾台詞,簡單來說就是提供一種特殊演員的模板。

簡要的UObject-Actor-Component UML類圖:

參考


博主最近在通過UE4搗弄關於地形生成的DEMO,順便學習UE4,因此接下來還會有幾篇UE4筆記和地形生成研究的博客,敬請期待:)

至於筆記博客的標題,算是致敬笨木頭前輩的《cocos2d-x游戲開發之旅》吧。

系列其他文章:Aery的UE4 C++開發之旅系列文章


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM