Aery的UE4 C++游戏开发之旅(2)编码规范
C++基础类型规范
由于PC、XBOX、PS4等各平台的C++基础类型大小可能不同(实际上绝大部分都是整型类型的大小不同),因此UE4提供了如下可移植基础类型的别名来统一规范类型大小:
- bool 代表布尔值(不会假定布尔尺寸)
- TCHAR 代表字符(不会假定TCHAR尺寸)
- uint8 代表无符号字节(1字节)
- int8 代表带符号字节(1字节)
- uint16 代表无符号“短”字符(2字节)
- int16 代表带符号“短”字符(2字节)
- uint32 代表无符号整数(4字节)
- int32 代表带符号整数(4字节)
- uint64 代表无符号“四字”(8字节)
- int64 代表带符号“四字”(8字节)
- float 代表单精确浮点(4字节)
- double 代表双精确浮点(8字节)
- PTRINT 代表可能含有指针的整数(不会假定PTRINT尺寸)
修正:应当在所有地方使用UE4提供的可移植类型,这在需要明确基础类型尺寸大小(例如需要序列化等功能)的情形提供良好的移植特性,应当成为一种习惯以避免以后一些不必要且难以察觉的跨平台类型bug
C++类、结构体、枚举规范
类 class
一般用UE4编辑器来创建C++类即可填补类所需要的宏,也就自动遵守了规范,无需说明。
结构体 struct
- 在UE4编辑器新建一个空类(None),顺便注意下结构体的命名规范
- 删掉里面类的内容,换成结构体的内容
#pragma once
#include "CoreMinimal.h"
#include "FMyStruct.generated.h"
USTRUCT(BlueprintType) //蓝图亦可访问该结构体类型
strcut FMyStruct
{
GENERATED_USTRUCT_BODY()
//示例
URPOPERTY(EditAnywhere,BlueprintReadWrite) //将字段公开给蓝图访问
float Value;
};
枚举 enum
- 在UE4编辑器新建一个空类(None),顺便注意下枚举的命名规范
- 删掉里面类的内容,换成枚举的内容
#pragma once
#include "EMyEnum.generated.h"
UENUM(BlueprintType) //蓝图亦可访问该枚举类型
enum class EMyEnum : uint8
{
//示例
Value0 UMETA(DisplayName = "枚举值0"),
Value1 UMETA(DisplayName = "枚举值1"),
Value2 UMETA(DisplayName = "枚举值2")
};
命名规范
-
命名(如类型或变量)中的每个单词需大写首字母,单词间通常无下划线
例如:Health 和 UPrimitiveComponent,而非 lastMouseCoordinates 或 delta_coordinates
-
bool变量必须以b为前缀(例如 bPendingDestruction 或 bHasFadedIn)
-
类型名前缀需使用额外的大写字母,用于区分类型名和变量名
例如:FSkin 为类型名,而 Skin 则是 FSkin 的实例
类型命名前缀规范如下:
类别 前缀 继承自 UObject U 继承自 AActor A 继承自 SWidget S 抽象界面类的前缀 I 结构体类的前缀 F 枚举类的前缀 E 模板类 T 其它多数类 F 部分子系统则以其他字母为前缀
模板实例化的Typedef不再是模板,并应加上相应前缀,例如:typedef TArray<FMytype> FArrayOfMyTypes;
-
蓝图命名:"BP"+类别缩写+"_"+名字
例如: BPA_Player
蓝图类别 前缀 蓝图Actor BPA_ 蓝图结构 BPS_ 蓝图枚举 BPE_ 蓝图接口 BPI_ 蓝图函数库 BFL_ 蓝图宏库 BML_
头文件包含规范
- 确保自己include的头文件不要放在 "XXX.generated.h" 文件下面,因为Unreal Header Tool编译工具默认这个文件就是头文件列表的最后一行了
源码文件规范
- 应将C++代码文件都保存为utf8格式:否则可能会出现在UE4蓝图中调用C++代码(函数、类等)时,出现注释乱码的情况
- 在文件结尾留一行空行:所有的.cpp和.h文件都应该留一行空行以便于更好的兼容gcc编译器
命名空间规范
- 不要在全局作用域内使用“using"声明,甚至包括在. cpp文件内也是如此;只可以在一个命名空间内或函数体内使用“using”声明命名空间
这里仅限定当using关键字作为命名空间语法使用时,其余用法不在此建议内(如定义模板别名时)
// Example
void FBlueprintNativeCodeGenManifest::InitDestPaths(const FString& PluginPath)
{
using namespace BlueprintNativeCodeGenManifestImpl;
//....
}
- 前置声明的类型要在各自的命名空间中声明,否则会出现链接错误
字符串规范
- 在字符串字面量周围使用 TEXT() 宏:若未使用,构建 FStrings 的代码将导致不理想的字符转换过程
"Hello World!"; //Not so well
TEXT("Hello World!"); //OK
- TCHAR字符串与char/wchar_t字符串的相互转换要使用到UE4提供的转换宏,但是使用转换宏时要注意:只在给函数传参时使用这个宏转换,千万不要保留指向它们的指针
SomeAPI(TCHAR_TO_ANSI(TcharString)); // OK
const char* SomePointer = TCHAR_TO_ANSI(TcharString); // Bad!!!
有关这两点规范更详细的解释可以看 Aery的UE4 C++游戏开发之旅(5)字符&字符串
错误处理规范
- 不要使用C++异常机制(try,catch),UE4代码默认是不支持的,推荐使用Assertions
//example
int i=1;
verify(i==0);
具体UE4提供的断言可查看:虚幻引擎4 官方文档 | 断言相关规范
注释规范
JavaDoc 规则
UE4支持基于JavaDoc规则自动从代码中提取注释并生成文档,所以注释可以采用JavaDoc形式
/**
* Check against another vector for equality, within specified error limits.
*
* @param V The vector to check against.
* @param Tolerance Error tolerance.
* @return true if the vectors are equal within tolerance limits, false otherwise.
*/
bool Equals(const FVector& V, float Tolerance=KINDA_SMALL_NUMBER) const;
对于简单的函数或方法,把参数说明放到函数的描述性注释中也是可以的
/**Create a copy of this vector, with its magnitude clamped between Min and Max.*/
FVector GetClampedToSize(float Min,float Max) const;
JavaDoc 注释规范可看参考链接。
使用第三方库 & 修改UE4引擎源码
引擎中包含的所有第三方代码都应该使用容易搜索的注释标签
// @third party code - BEGIN Physx
#include <physx.h>
// @third party code - END Physx
// @third party code - BEGIN MSDN SetThreadName
// [http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx]
// Used to set the thread name in the debugger
...
// @third party code - END MSDN SetThreadName
当需要修改引擎中所使用的某个库的代码时,需要确保在修改处增加//@UE4注释标记,同时要加上修改原因。这样会使在合并该库的新版本时更加容易,而且也可以让授权方很容易找到所有修改
//@third party code BEGIN SIMPLXGON
/** Get the Hash for the file being imported,Provides enormous speed jimpouements for large CA0 file imports */
static FMD5Hash GetFileHash()
{
return FileHash;
}
//@third party code ENDSIMPLYGON
参考
系列其他文章:Aery的UE4 C++开发之旅系列文章
作者:KillerAery
出处:http://www.cnblogs.com/KillerAery/
本文版权归作者和博客园共有,未经作者同意不可擅自转载,否则保留追究法律责任的权利。