3 - UE代码规范
腾讯2024游戏客户端公开课笔记,UE的C++代码规范部分,这节课的目标是:
- 了解通用代码规范;
- 了解UE5中C++代码规范
- 了解UE5中的标识符
通用代码规范
代码规范就是编写某语言的一系列指导方针,包括代码风格、缩进、注释、命名等方面,通常由团队/组织/公司制定。
代码需要长期维护,且一份代码可能会被多个人所查看与编辑。一致的代码规范可以提高代码的可维护性,可读性。从而在一定程度上增加开发效率。
常见的代码规范有谷歌的、腾讯的等,可以通过.clang-format
工具来帮忙一键格式化代码。
UE5的C++代码规范
有人说UE5使用的是U++,而不是C++,这是因为它自己实现了更高效的标准库,要想编程得用它提供的容器。UE5也有自己的一套代码规范,可在这里查看。常用的代码规范如下:
命名
变量命名要求清晰、明确且避免过度缩写。此外还要遵循大驼峰式命名(CamelCase),bool类型需要加b前缀。遵循大驼峰式命名的原因是,UE5会将一些变量名反射到编辑器中,大驼峰变量名会被自动分词。例如TestCase
会变成Test Case
。
UE5对类的命名也有严格的命名规范,如果不遵循可能会出现编译错误:
开头字母 | 含义 | 示例 |
---|---|---|
T | 模板类 | TMap |
U | 继承自UObject的类 | UMoviePlayerSettings |
A | 继承自AActor的类 | APlayerCameraManager |
S | 继承自SWidget的类 | SCompoundWidget |
I | 抽象接口类 | INavNodeInterface |
E | 枚举类 | EAccountType |
F | 其他类 | FVector |
数据类型
UE5中常见的数据类型如下:
数据类型 | 意义 | 大小(字节) |
---|---|---|
bool | 布尔值 | sizeof(bool) |
TCHAR | 字符 | sizeof(TCHAR) |
int8/uint8 | 有符号/无符号字节 | 1 |
int16/uint16 | 有符号/无符号短整数 | 2 |
int32/uint32 | 有符号/无符号整数 | 4 |
int64/uint64 | 有符号/无符号长整数 | 8 |
float | 单精度浮点数 | 4 |
double | 双精度浮点数 | 8 |
PTRINT | 与指针同样大小的整数 | sizeof(PTRINT) |
如果要在UE5中使用字符串,需要用UE定义的一些容器,如FString/FText/FName/TCHAR
等。如果要在UE5中使用容器,应该避免使用C++提供的STL库,而是使用它自定义的TArray/TMap等,这是因为容器的内存分配必须受到引擎的控制。
此外,在UE中类的代码中可能会发现如下情况:
UPROPERTY()
uint8 bXXXX:1;
这句代码的意思是只用一个bit存储该变量,以节省空间。
命名空间
在命名空间方面,需要注意以下几点:
- UnrealHeaderTool仅支持全局命名空间的类型;
- 不要在全局命名空间使用using声明;
- 一些宏在命名空间内可能会失效,可以尝试UE_xxx。
UE5中的标识符
UE5中可以通过一些标识符来对变量、类、函数等做一些约束。标识符的通用结构如下图所示:
原理
编写好一个文件后,UHT会将头文件通过反射生成xxx.generated.h/cpp
,最后会让UBT编译。
UPROPERTY
这种标识符会将被标注的成员反射到编辑器中,并且根据限定符的不同,反射的结果也有所不同。例如有一个结构体FCat,并声明了两个FCat变量:
UPROPERTY(EditAnyWhere, Category="111")
FCat Cat1;
UPROPERTY(EditAnyWhere, Category="222", meta=(ShowOnlyInnerProperties))
FCat Cat2;
那么它们在编辑器中反射的结果如下:
// 第一个
111
Cat1
xxx
xxx
// 第二个
222
xxx
xxx
常用限定符的解释如下:
VisibleAnywhere
:在编辑器中只读;EditAnyWhere
:支持在编辑器内编辑;BlueprintReadOnly
:蓝图中只读;BlueprintReadWrite
:蓝图中读写;Category
:分类,是编辑器中展开收起的标签名。例如:
UPROPERTY(EditAnyWhere, Category="Animals") bool bIsCute; UPROPERTY(EditAnyWhere, Category="Animals|Dogs") FString BarkWord; UPROPERTY(EditAnyWhere, Category="Animals|Birds") int32 FlyingSpeed;
它们在编辑器中反射的结果如下:
Animals Is Cute Dogs Bark Word Birds Flying Speed
AdvancedDisplay
:对于一些低频修改的属性,或者是只针对进阶者使用的属性,可以使用此项标注。这样在编辑器中需要展开才能看到此项。meta
:属性的元信息,用来辅助反射系统。例如:ShowOnlyInnerProperties
可以忽略变量名;DisplayName
可以自定义在编辑器中展示的命名;DisplayPriority
可以决定该属性显示的优先级;ClampMin, ClampMax
可以决定该属性的范围;
UFUNCTION
专门给函数使用的标识符,它的常用限定符如下:
BlueprintCallable
:支持在蓝图中使用;Category
:在蓝图中被反射到的类别;meta
:可以通过meta = (Xxx = "xxx")
来给函数任意位置的参数赋默认值,只在蓝图节点中有效。
UCLASS
专门给类使用的标识符,需要将#include "Xxx.generated.h"
放在包含列表的最后。并且在类中需要添加GENERATED_BODY()
宏。
它的常用限定符如下:
BlueprintType
,Blueprintable
:方便在蓝图中访问;config=Xxx
:应用XXX的设置;meta
:ShortToolTip
可以设置在蓝图中的简短提示;
USTRUCT
专门给结构体使用的标识符,需要在结构体中添加GENERATED_USTRUCT_BODY()
宏。
UENUM
专门给枚举类使用的标识符。
拓展阅读
- UE5官方文档:虚幻引擎元数据说明符
- UE5标识符详解 | 史上最全 - 知乎 (zhihu.com)