参考各种博客及 UE文档
帕斯卡命名法(PascalCase) PascalCase 是指:单词均首字母大写,不使用空格和下划线_,例如:GameScore ,而不是 gameScore ,game_score ,Game_Score等。。
但不包括额外的前缀和后缀。
之所以需要规范,是因为一套软件 80% 的生命周期都是协作和维护。
一. c++
1. c++类命名
类名应该包括一个大写字母前缀,用于区分类型名和变量名,比如 FString String
要比 String String
容易辨识的多。
可能的前缀
-
A 派生自 AActor,如 AAcontroller 。
-
U派生自 UObject ,如 UComponent 。
-
S派生自 SWidget(Slate UI) ,如 SButton 。
-
E 枚举类,如 ENotificationType 。
-
I 接口类,如 IInteract 。
-
T 模板类,如 TArray 。
-
F 其余类,如 FVector 。
注意大部分其他类都以F为前缀,但在某些
子系统
可以使用其他字母
作为前缀。
- 除了前后缀,均遵循
PascalCase
- 所有暴露给蓝图的变量,函数,类等均应遵循蓝图对应的规范。
2. c++类成员
-
均遵循 PascalCase,布尔型变量还需加上
b 前缀
。 -
所有变量应
逐个声明
,以便对变量的含义提供注释,推荐使用多行注释。可以使用空行给变量分类。 -
类型和变量的命名为名词。 函数名是动词。
-
对于过程(没有返回值的)函数命名时应该使用一个强动词加一个对象。但命名时要避免使用"Handle"和"Process"开头,这些动词表达的意思模糊不清。
所有返回布尔值的函数都应该询问:返回值是真还是假这个问题,如:IsFresh(),CanFresh(),HasFresh()。
-
如果函数参数是可写引用,那么推荐使用 Out 作为参数名称的前缀,可以清晰地表示该值会被函数改变。同时,对于其他函数参数,可以使用 In 前缀。不遮挡类成员名称时可以不使用。
指针和引用应该仅有一个空格,该空格位于指针/引用的右侧。 这样使得可以快速地在文件中查找某种特定类型的所有指针或引用。如
FString* EncodeString
,而不是FString *EncodeString
,FString * EncodeString
。 -
在具备可移值的代码中,请使用UE自带的基础类型,而非C++原生类型。
3. 注释
-
Epic发布时提供的任何源码文件 (.h, .cpp, .xaml等等) 都必须包含版权声明,将其放置在文件的第一行。版权声明的格式必须完全符合以下格式:
版权1998-2014 Epic Games, Inc. 版权所有
。推荐在自己代码也加入类似的声明。 -
UE4中应该在公开声明方法的地方提供注释。方法注释应该仅包含和方法的函数调用相关的信息,包括可能和该函数调用相关的方法重载的任何信息。关于那些和函数调用无关的方法及其重载方法的实现细节,应该在方法实现内部进行注释。
-
类注释中都包括哪些内容?
- 这个类解决的问题的说明。为什么创建这个类?
、
方法注释的所有组成部分的意思?
-
首先是函数的作用;这记录了 函数所解决的问题 。正如上面所说的,注释表明 意图 ,而代码记录 实现 。
-
然后是参数注释;每个参数注释应该包含了度量单位、期望值的范围、不符合要求的值、及 状态/错误 代码的意思。
-
然后是返回值注释,它说明了期望的返回值的信息,注释方法和给输出变量添加注释一样。
、
示例
//Copyright Moota, Private. All Rights Reserved. #pragma once #include "CoreMinimal.h" #include "UObject/Object.h" #include "DemoOne.generated.h" /** * 用于测试的类 */ UCLASS() class DEMOCRAFT_API UDemoOne : public UObject { GENERATED_BODY() public: /** * 将两个数相加 * @param NumberOne - 操作数1 * @param NumberTwo - 操作数2 * @return 返回操作数1和操作数2相加的结果 */ static int32 AddTwoNumber(const int32& NumberOne,const int32& NumberTwo); }; inline int32 UDemoOne::AddTwoNumber(const int32& NumberOne,const int32& NumberTwo) { return NumberOne+NumberTwo; }
- 这个类解决的问题的说明。为什么创建这个类?
二. 编辑器
1. 命名禁止字符和推荐字符
禁止使用以下字符
- 任何形式的空格
- 反斜杠\
- 不明符号 #@%¥$&*^!
- 任何Unicode字符
推荐使用以下字符
- ABCDEFGHIJKLMNOPQRSTUVWXYZ
- abcdefghijklmnopqrstuvwxyz
- 1234567890
- _
这样可以最大确保所有命名数据在所有平台,所有工具,所有代码下的兼容性。
2. 资产命名规则
3. 资产详细命名规则
-
标准格式
[AssetTypePrefix]_[AssetName]_[Descriptor]_[OptionalVariantLetterOrNumber] 【资产类型】_【资产名称】_【资产用法/后缀】_【多个变体版本】
- AssetTypePrefix 将表明资产的类型,使用类型的缩写,详情请参阅上表。 - AssetName 是资产的名称。 - Descriptor 将提供资产的更多上下文,表明其用法。例如,纹理是正常贴图还是不透明度贴图。 - OptionalVariantLetterOrNumber 是可选的,用于区分资产的多个版本或变体。
比如
T_Rock_A_1表示版本为1的-用作透明度的-关于岩石的-纹理资源,
T_Wood_N_Ancient表示风格为古老的-用作法线的-关于木头的-纹理资源,
如果不存在后缀和变体,Descriptor和Variant可以独立省略。
4. 资源文件相关规范
- 文件名和目录使用 PascalCase。
- 使用推荐字符,不使用禁止字符。
- 不使用全局资产,每个资产都必须属于某个指定的文件夹。
- 所有 Map 文件都属于一个名为 Maps 的文件夹,无论具体项目采用何种地图组织系统,所有级别都应属于/Content/Project/Maps。
- 为关键蓝图和其他资产使用核心文件夹,将 /Content/Project/Core 文件夹用于对项目工作绝对重要的资产。例如,基本 GameMode、Character、PlayerController、GameState、PlayerState 和相关的蓝图应该存在于此。
- 不要创建名为 Assets 或 AssetTypes 的文件夹,这是多余的,所有资产都是资产。
- 合理使用命名过滤系统查看资产。
- 如果存在全局可重用的资产,则这些资产应位于 Content/Project/XXXLibrary 中。其他资产同理
- 不要有空文件夹。它们使内容浏览器变得混乱,而且存在删除失败的问题,请修复重定向器。
- 如果是实验性资产,不被正式项目使用,应存放于 Developer 文件夹。
1. 静态网格体
- 所有网格都必须有 UV
- 所有网格都不能有光照贴图的重叠 UV
- 应正确设置 LOD
- 模块化的无插槽资产应该可无缝地组合
- 所有网格都必须有碰撞
- 所有网格都应正确缩放
2. 纹理
- 除 UI 纹理外,所有纹理的尺寸都必须是 2 的幂的倍数。纹理不必是方形的。
例如,128x512、1024x1024、2048x1024、1024x2048、1x512。 - 纹理密度要均匀
- 纹理不应大于 8192
- 纹理应该正确分组
3. Niagara
不使用禁止字符,因为当在 Niagara 中使用 HLSL 或其他脚本编写方式并尝试引用变量时,存在崩溃问题。
4. 关卡/地图
- 没有错误或警告,如果一个关卡加载有任何错误或警告,应立即修复它们。
- 应构建光照,在进行测试/内部/运输构建或任何要分发的构建时,应始终构建光照。
- 关卡不应在玩家可见的所有区域中出现任何 z-fighting。
5. 市场特定规则
如果一个项目要在 UE4 Marketplace 上出售,它必须遵循这些规则。
- 概述关卡(Overview)
如果您的项目包含应可视化或演示的资产,则您的项目中必须有一个包含名称“Overview”的地图。
如果是可视化资产,则此概览图应根据 Epic 的指南进行设置。 - 演示关卡(Demo)
关卡示例或附带某种教程的资产,则您的项目中必须有一个包含名称“Demo”的地图。此关卡还应包含以某种形式说明如何使用您的项目的文档。请参阅 Epic 的内容示例项目以获取有关如何执行此操作的良好示例。
6. 蓝图
- 所有蓝图都应以零警告和零错误进行编译。 如有问题,您应该立即修复蓝图警告和错误。不要忽视警告。
- 损坏的蓝图可能会导致以其他方式表现出来的问题,例如损坏的引用、意外行为、Cook失败和频繁的不必要的重新编译。 一个坏的蓝图有能力破坏你的整个游戏!!!
- 不要将损坏的蓝图提交给源代码控制。
- 蓝图风格
- 线条不要乱七八糟
- 对齐线条而不是节点
- 请始终拉直白色执行线
- 进行合理注释
- 转换可能出错的位置要有提示
- 不要有没目的、不执行的悬空节点
7. 变量
-
所有变量都应采用 PascalCase 的形式。
-
所有非布尔变量名称尽量是名词。
-
所有布尔值都应以小写 b 为前缀,且尽量是形容词。
不要带有 Is,Has,Can等提问前缀。这是为返回Bool的函数保留的。
坏的命名 bIsDead、bIsHostile
好的命名 bDead、bHostile
尽量不要使用动词,例如 bRunning。动词带有复杂的状态,请使用枚举替换,且所有复杂的状态都应使用枚举替换。 -
所有变量命名不需要重复体现上下文关系,蓝图中的所有变量引用始终具有上下文关系。
坏的命名 PlayerKills、MyCharacterName、ChosenCharacterSkin
好的命名 Kills、Name、Skin
所有这些变量都被冗余命名,来提示该变量属于 PlayerCharacter,但是通过上下文已经知道变量的主拥有者是 PlayerCharacter了。 -
变量命名不要包含基础类型名称
好的命名 Score、Kills 、Description
坏的命名 ScoreFloat、FloatKills、DescriptionString
此规则的唯一例外是当变量表示要计算的“数量”,并且使用带变量类型的名称易阅读时。
示例:围栏生成器需要生成 X 个柱子(Post)。将 X 存储在 PostsNum 或 PostsCount 中,而不是 Num,Count,因为 可能存在多个需要表示数量关系的变量。 -
变量命名包括非基础类型名称
如果一个类拥有一个复杂变量的实例,即如果一个 BP_PlayerCharacter 拥有一个 BP_Hat,它应该被存储为变量类型,不要修改为其他名称。
好的命名 Hat、Flag 、Ability
坏的命名 MyHat、MyFlag 、PlayerAbility。 -
数组
数组命名为复数名词,且遵循上述规则。
好的命名 Targets、Hats、 EnemyPlayers
坏的命名 TargetList、HatArray、EnemyPlayerArray。 -
可编辑变量
所有不能安全更改或不应向设计人员公开的变量不应标记为可编辑。 -
分类
如果一个类只有少量变量,可以使用默认类别。
如果一个类具有中等数量的变量 (5-10),则所有可编辑变量都应分配一个非默认类别Config。
如果一个类有大量的变量,那么所有可编辑变量都应该在 Config 类别下划分为出对应的子类别。
所有不可编辑的变量应独立于Config创建描述其用途的类别。
您可以使用管道字符 | 来定义子类别,即 Config | Animations。 -
私有变量
如果知道一个变量只能在定义它的类中访问,请将变量标记为私有。不要轻易公开变量。 -
高级显示
如果一个变量可编辑的,但通常不变,请将其标记为高级显示,这可以使得变量隐藏于详情面板,节省展示空间。 -
配置变量
配置变量在 C++ 中用于具有较少更改率的变量。过多使用会使得设计师难以控制蓝图行为。
8. 函数、事件和事件分发器
- 函数命名的思考方向
是纯函数吗?
它是在获取状态信息吗?
是处理程序吗?
是 RPC 吗?
它的目的是什么? - 所有函数都应该是动词。
- 所有函数尽可都能用现在时来表达。
- 使用通知变量复制的所有函数都应具有 OnRep_Variable 的形式。这是由蓝图编辑器强制执行的。
- 编写一个不改变任何对象的状态或修改任何对象并且纯粹用于获取,计算,返回布尔值的函数时,应该提问,可以带有Is,Has,Can,Was前缀。
好的命名
IsVisible - 是否可见
HasWeapon - 是否有武器,“有”是一个动词。
WasCharging - 是否在充电,“Was”是“be”的过去式。
CanReload - 是否可重新加载,“Can”是一个动词。
坏的命名
Fire - 着火了吗?还是开火吗?
OnFire - 可能与用于触发的事件调度程序混淆。
Dead - 死了吗?设置死亡?
Visible - 获取可见吗?设置可见性? - 事件处理程序和调度程序应以 On 开头并尽量遵循动词规则。
有一些框架中用Handle来表示事件响应,但在虚幻中建议使用 On 代替 Handle
好的命名
OnDeath - 在死亡时;游戏中的常见搭配
OnReceiveMessage - 在接收消息时
OnTargetChanged - 在目标变更时
OnClick - 在点击时
坏的命名
OnData - 在数据时
OnTarget - 在目标时
HandleMessage - 处理消息
HandleDeath - 处理死亡 - 远程过程调用应以目标为前缀
每次创建 RPC 时,它都应该以 Server、Client 或 Multicast 作为前缀。没有例外。
好的命名
ServerFireWeapon - 服务器中的开火武器
ClientNotifyDeath - 客户通知死亡
MulticastSpawnTracerEffect - 多播创建跟踪特效
坏的命名
FireWeapon - 不表示它是某种 RPC。
ServerClientBroadcast - 令人困惑。
AllNotifyDeath - 使用多播,而不是全部。
ClientWeapon - 没有动词,模棱两可。 - 所有函数都必须有返回节点,没有例外。
- 任何函数都不应有超过 50 个节点
任何过大的功能都应该分解成更小的功能。
以下节点不计算在内,因为它们被认为不会增加功能复杂性:
Comment - 注释
Route - 变更路线节点
Cast - 类型转换
Getting a Variable - 获得一个变量
Breaking a Struct - 分解一个结构体
Function Entry - 函数入口
Self - 自身 - 所有公共功能都应该有描述(Comment)
以便 其他人 可以更轻松地理解和使用您的蓝图 API。 - 所有自定义静态插件的BlueprintCallable函数必须按插件名称分类
例如,Zed Camera Interface 或 Zed Camera Interface | Image Capturing。