写在前面
主要是介绍一下UE4中的一些常用概念。
参考的博客如下:
- UE4常用逻辑关系和说明;
- UE4入门学习4:C++编程介绍;
- UE4中基础的类及其之间的关系;
- [官方] 虚幻引擎 4 术语;
- 《图解UE4渲染体系》Part 0 引擎基础
一、UE4世界结构
UE4世界的主要结构如下:
- World (当前游戏世界,可以包含多个Level)
- Level (关卡地图,每个关卡被保存为单独的
.umap
文件,可以有多个Sub-Levels)- Actor(基本实体,可以被动态添加到Level中)
- Component(组件,隶属于Actor的功能对象体,可以为Actor赋予视觉、声音、运动等表现)
- Pawn(特殊的Actor,表示游戏中的生命体)
- Controller(控制器,负责接受来自玩家或者AI的输入,赋予Pawn以玩家或者类似玩家的行为)
- Character(特殊的Pawn,表示游戏中的人,增加了碰撞组件
CapsuleComponent
和人物运动组件CharacterMovementComponent
)
- Actor(基本实体,可以被动态添加到Level中)
- Level (关卡地图,每个关卡被保存为单独的
- GameMode(定义游戏规则)
- GameState(游戏状态,包含玩家列表、得分情况、玩家任务清单等)
- PlayerState(玩家的状态,包含名字、得分、等级等)
Controller有两种类型,分别是PlayerController和AIController;
隶属于PlayerController的一些模块如下:
- HUD(Heads-Up Display,在屏幕上显示二维的UI信息,如血条和玩家名称等,每个PlayerController只有一个AHUD对象)
- Camera(相当于人的眼睛,提供玩家的视角,每个PlayerController只有一个PlayerCameraManager对象)
PlayerController和Pawn的关系如下:
二、UE4基本类结构
- 其实上面所提到的世界中的大部分模块都是一个类,但这里只介绍一些常用的类;
1. UObject
-
是所有Object的基类;
-
功能包括垃圾回收、元数据、在磁盘和网络中的序列化、类属性和函数的运行时反射和蓝图集成等;
-
不能被添加到关卡Level中,也不能在蓝图中使用,但可以包含数据和函数;
-
常用的宏:
UCLASS
:声明类;USTRUCT
:声明结构体;UFUNCTION
:声明成员函数;UPROPERTY
:声明成员变量;
-
一个例子如下:
USTRUCT()
struct FVector2D
{
UPROPERTY()
float X;
UPROPERTY()
float Y;
UFUNCTION()
float GetLength() const;
}
-
下面介绍一下一些常用宏的说明符;
-
(1)
UPROPERTY()
的常用说明符如下:VisibleAnywhere
:在蓝图面板的详细信息和主面板的蓝图实例的详细信息窗格中都可见,也就是变量在所有的属性窗口中均可见,但无法编辑;VisibleDefaultsOnly
:仅在蓝图面板的详细信息窗格中可见,同时无法编辑,也就是蓝图类内变量可见,可以得知一个相对公共的设定值;VisibleInstanceOnly
:仅在主面板的蓝图或C++类实例的详细信息窗格中可见,同时无法编辑,也就是蓝图对象内变量可见,只能得知一个相对私有的设定值;EditAnywhere
:在蓝图面板的详细信息和主面板的蓝图实例的详细信息窗格中都可见且可被修改,也就是变量在所有的属性窗口中均可见且可被修改;EditDefaultsOnly
:仅在蓝图面板的详细信息窗格中可见且可被修改,修改的是类的值,将影响该类之后生成的所有实例;EditInstanceOnly
:仅在主面板的蓝图或C++类实例的详细信息窗格中可见且可被修改,修改对象的值,仅影响当前拖动到地图中生成的实例;BlueprintReadOnly
:可在蓝图中读取值,但不能修改值;BlueprintReadWrite
:既可在蓝图中读取值,也可以在蓝图中修改值;Category="xxx|xxx"
:将当前变量分组到文件夹中,|
符号用于创建子文件夹,注意引号内的所有空格均有意义,注意删掉无意义空格;DisplayName="xxx"
:更改在信息窗格中显示的文本标签名字;ToolTip="xxx"
:当鼠标悬停到信息窗格的对应属性时出现的提示信息文本,如果没有,则默认使用代码中的注释内容;
-
参考:
- UE4 C++学习 浅析UProperty属性说明符;
- [官方] https://docs.unrealengine.com/5.0/zh-CN/unreal-engine-uproperty-specifiers/;
-
一些补充说明:
- 所有带
Edit
的说明符和带Visible
的说明符不能同时出现,只能出现其中一种; BlueprintReadOnly
和BlueprintReadWrite
起码要出现一个,不然在蓝图中右键是找不到这个属性的;
- 所有带
-
(2)
UFUNCTION()
的常用说明符如下:BlueprintCallable
:该函数可以在蓝图中被调用;BlueprintImplementableEvent
:这个函数只能用蓝图实现,不能用C++实现;BlueprintNativeEvent
:这个函数必须用蓝图重写实现,有默认调用的方法(以_Implementation
为后缀,需要用C++实现),因此在蓝图中是重写实现,不能用C++重写;BlueprintPure
:这个函数在蓝图中没有接口,不能被其他函数调用,只能用它的返回结果,而且不会缓存它的计算结果,每次调用时均会执行一次计算,可以参考:【UE·C++】BlueprintCallable与BlueprintPure区别;DisplayName
和ToolTip
均是元数据类型,使用时应写meta = (MetaTag1="xxx", MetaTag2="xxx", ...)
,更多关于元数据的介绍参考官方文档:https://docs.unrealengine.com/4.27/zh-CN/ProgrammingAndScripting/GameplayArchitecture/Metadata/;
-
参考:
- UE4 C++学习 UFunction函数说明符;
- [官方] https://docs.unrealengine.com/5.0/zh-CN/function-specifiers/;
-
一些补充说明:
BlueprintCallable
和BlueprintPure
只能出现一个,前者仅在第一次调用时计算结果,后者是每次调用均重新计算结果,因此计算的开销很大;
-
(3)
UCLASS()
的常用说明符如下:Blueprintable
:该类可以在主面板右键创建基于此类的蓝图类;
-
参考:
- [官方] https://docs.unrealengine.com/5.0/zh-CN/class-specifiers/;
2. AActor
- 继承于
UObject
; - 是所有Actor的基类;
- 有一个RootComponent成员变量,用于保存组件树中的根组件,结构示意如下:
- 一个Actor如果想被放进Level中,就必须先赋予
USceneComponent * RootComponent
一个SceneComponent对象,因为SceneComponent对象能为Actor提供变换信息(位置、旋转和缩放等); - 生命周期的事件:
BeginPlay()
:Actor对象首次在Gameplay中存在时调用;Tick()
:每帧调用一次;EndPlay()
:Actor对象离开Gameplay空间时调用;
3. UActorComponent
-
是所有Component的基类;
-
不可以单独存在,只能作为Actor中的成员变量使用;
-
派生的Component类包括:
USceneComponent
:使Actor有位置变换的能力,包括位移、旋转和缩放等;UPrimitiveComponent
:使Actor有被渲染的能力;UMeshComponent
:使Actor有形状外貌的能力;UStaticMeshComponent
:静态网格体组件,继承前面3个类,是UE4的基本场景构建单位,最为常用;UChildActorComponent
:可以作为子节点搭建一棵组件树;
-
它们的关系如下:
-
其他的组件介绍可以参考官方博客:https://docs.unrealengine.com/4.27/zh-CN/Basics/Components/;
4. APawn
- 继承于
AActor
; - 有物理表示和基本的移动能力;
- 可以被PlayerController或者AIController实现控制;
5. ACharacter
- 继承于
APawn
; - 在Pawn的基础上默认挂载了三个组件:
USkeletalMeshComponent
:骨骼网络组件;UCharacterMovementComponent
:人物移动组件,包括走、跑、跳、飞、游泳等;UCapsuleComponent
:碰撞组件;
APawn
和ACharacter
之间的关系如下:
6. AController
- 可以和Pawn关联;
- Controller和Pawn的关系:
- Controller的抽象级别要更高一点,生命周期也更长,相当于一个控制中心,而Pawn则为一个被控制的实体;
- Controller可以搭配不同的Pawn,并负责向Pawn输出某些共有的控制逻辑,或者说是一套行为准则;
- 每个Pawn只能认领一个Controller,并接受它所输出的行为准则,当然,它也可以更换不同的Controller获得不同的行为准则;
- Controller和Pawn的关系示意图如下:
三、代码命名规范
- 类、变量和函数的命名均用大驼峰式,首字母大写;
- 每个类的命名前面均需要加前缀,如下:
A
:派生自AActor
的类;U
:派生自UObject
的类;S
:派生自SWidget
的类;E
:枚举类;I
:接口类;T
:模板类;F
:除上述的其他类;
- 和类对应的C++文件名则不加前缀;
- 变量的命名仅布尔变量需要增加前缀,如下:
b
:布尔变量;
- 如果返回值是布尔类型的函数的命名需要增加前缀,如下:
Is
或者Should
:返回值是布尔类型的函数;
四、常用变量类型
1. 基本数据类型
bool
:布尔类型;int8 / uint8
:整数,8bit;int16 / uint16
:整数,16bit,相当于short int;int32 / uint32
:整数,32bit,相当于int;int64 / uint64
:整数,64bit,相当于long long int;float
:单精度浮点数,32bit;double
:双精度浮点数,64bit;
2. 指针类型
PTRINT
:和指针同样大小的整数;
3. 字符串类型
TCHAR
:字符,相当于char;FString
FText
FName
4. 容器类型
TArray
:动态数组,相当于vector;TDoubleLinkedList
:双向链表,相当于list;TMap
:字典,相当于unordered_map;TSet
:集合,相当于unordered_set;TQueue
:队列,相当于queue;
5. 文件相关类型
FFileManagerGeneric
FArchive
:序列化相关操作类;
6. 智能指针类型
TSharedPtr
:共享指针,针对普通的C++对象;TWeakPtr
:弱指针,针对普通的C++对象;TWeakObjPtr
:针对UObject对象;TAutoPtr
TScopedPtr
TUniquePtr
7. 其他类型
-
FVector
:空间坐标向量,有三个成员变量,分别代表X轴、Y轴和Z轴;- 可以参考博客:UE4 FVector向量的一些知识;
-
FRotator
:旋转向量,有三个成员变量Pitch、Yaw和Roll,分别代表绕Y轴、Z轴和X轴旋转;- 注意如果该变量可以在细节面板上显示,则会自动转换为X、Y和Z,此时就各自对应X轴、Y轴和Z轴;
- 也就是说在Editor中显示是正常的顺序;
- 但在C++代码中是Y轴、Z轴和X轴的顺序;
-
FMath
:数学函数功能类;
五、注释
1. 函数注释
- 遵循JavaDoc形式,如下:
/*
* 函数功能说明
*
* @param 参数1 参数1说明
* @param 参数2 参数2说明
* @return 返回值说明
*/
返回值类型 函数名(参数1, 参数2);
- 或者用一行注释说明,如下:
/** 函数功能及参数说明 */
返回值类型 函数名(参数1, 参数2);
2. 函数内注释
- 在代码的上一行独立注释,如下:
...
// 注释内容
代码内容;
...
- 如果注释的内容太长可以手动分开多段来写;
六、资源命名规范
-
资源均放在
Content
文件夹下,每个资源文件的命名要加上前缀,如下:L_
:关卡(Level / Map);BP_
:蓝图(Blueprint);S_
:静态网格(StaticMesh);SK_
:骨架网格(SkeletalMesh);T_
:纹理(Texture);PS_
:粒子系统(Particle System);WBP_
:组件蓝图(Widget Blueprint);
-
存放资源的文件夹也要对应命名,如下:
Maps
:关卡;Blueprints
:蓝图;Animations
:动画;Sounds
:音频;Materials
:材质;Textures
:纹理;Effects
:特效;