UE-c++规范命名

参考各种博客及 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为前缀,但在某些 子系统 可以使用 其他字母 作为前缀。

  1. 除了前后缀,均遵循 PascalCase
  2. 所有暴露给蓝图的变量,函数,类等均应遵循蓝图对应的规范。

2. c++类成员

  1. 均遵循 PascalCase,布尔型变量还需加上 b 前缀

  2. 所有变量应 逐个声明,以便对变量的含义提供注释,推荐使用多行注释。可以使用空行给变量分类。

  3. 类型和变量的命名为名词。 函数名是动词。

  4. 对于过程(没有返回值的)函数命名时应该使用一个强动词加一个对象。但命名时要避免使用"Handle"和"Process"开头,这些动词表达的意思模糊不清。

    所有返回布尔值的函数都应该询问:返回值是真还是假这个问题,如:IsFresh(),CanFresh(),HasFresh()。

  5. 如果函数参数是可写引用,那么推荐使用 Out 作为参数名称的前缀,可以清晰地表示该值会被函数改变。同时,对于其他函数参数,可以使用 In 前缀。不遮挡类成员名称时可以不使用。

    指针和引用应该仅有一个空格,该空格位于指针/引用的右侧。 这样使得可以快速地在文件中查找某种特定类型的所有指针或引用。如 FString* EncodeString,而不是 FString *EncodeStringFString * EncodeString

  6. 在具备可移值的代码中,请使用UE自带的基础类型,而非C++原生类型。

3. 注释

  1. Epic发布时提供的任何源码文件 (.h, .cpp, .xaml等等) 都必须包含版权声明,将其放置在文件的第一行。版权声明的格式必须完全符合以下格式:版权1998-2014 Epic Games, Inc. 版权所有。推荐在自己代码也加入类似的声明。

  2. UE4中应该在公开声明方法的地方提供注释。方法注释应该仅包含和方法的函数调用相关的信息,包括可能和该函数调用相关的方法重载的任何信息。关于那些和函数调用无关的方法及其重载方法的实现细节,应该在方法实现内部进行注释。

  3. 类注释中都包括哪些内容?

    • 这个类解决的问题的说明。为什么创建这个类?

    方法注释的所有组成部分的意思?

    • 首先是函数的作用;这记录了 函数所解决的问题 。正如上面所说的,注释表明 意图 ,而代码记录 实现 。

    • 然后是参数注释;每个参数注释应该包含了度量单位、期望值的范围、不符合要求的值、及 状态/错误 代码的意思。

    • 然后是返回值注释,它说明了期望的返回值的信息,注释方法和给输出变量添加注释一样。

    示例

    //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. 资产详细命名规则

  1. 标准格式

    	[AssetTypePrefix]_[AssetName]_[Descriptor]_[OptionalVariantLetterOrNumber]
    	【资产类型】_【资产名称】_【资产用法/后缀】_【多个变体版本】
    
     - AssetTypePrefix 将表明资产的类型,使用类型的缩写,详情请参阅上表。
     - AssetName 是资产的名称。
     - Descriptor 将提供资产的更多上下文,表明其用法。例如,纹理是正常贴图还是不透明度贴图。
     - OptionalVariantLetterOrNumber 是可选的,用于区分资产的多个版本或变体。
    

    比如
    T_Rock_A_1表示版本为1的-用作透明度的-关于岩石的-纹理资源,
    T_Wood_N_Ancient表示风格为古老的-用作法线的-关于木头的-纹理资源,
    如果不存在后缀和变体,Descriptor和Variant可以独立省略。

4. 资源文件相关规范

  1. 文件名和目录使用 PascalCase。
  2. 使用推荐字符,不使用禁止字符。
  3. 不使用全局资产,每个资产都必须属于某个指定的文件夹。
  4. 所有 Map 文件都属于一个名为 Maps 的文件夹,无论具体项目采用何种地图组织系统,所有级别都应属于/Content/Project/Maps。
  5. 为关键蓝图和其他资产使用核心文件夹,将 /Content/Project/Core 文件夹用于对项目工作绝对重要的资产。例如,基本 GameMode、Character、PlayerController、GameState、PlayerState 和相关的蓝图应该存在于此。
  6. 不要创建名为 Assets 或 AssetTypes 的文件夹,这是多余的,所有资产都是资产。
  7. 合理使用命名过滤系统查看资产。
  8. 如果存在全局可重用的资产,则这些资产应位于 Content/Project/XXXLibrary 中。其他资产同理
  9. 不要有空文件夹。它们使内容浏览器变得混乱,而且存在删除失败的问题,请修复重定向器。
  10. 如果是实验性资产,不被正式项目使用,应存放于 Developer 文件夹。

1. 静态网格体

  1. 所有网格都必须有 UV
  2. 所有网格都不能有光照贴图的重叠 UV
  3. 应正确设置 LOD
  4. 模块化的无插槽资产应该可无缝地组合
  5. 所有网格都必须有碰撞
  6. 所有网格都应正确缩放

2. 纹理

  1. 除 UI 纹理外,所有纹理的尺寸都必须是 2 的幂的倍数。纹理不必是方形的。
    例如,128x512、1024x1024、2048x1024、1024x2048、1x512。
  2. 纹理密度要均匀
  3. 纹理不应大于 8192
  4. 纹理应该正确分组

3. Niagara

不使用禁止字符,因为当在 Niagara 中使用 HLSL 或其他脚本编写方式并尝试引用变量时,存在崩溃问题。

4. 关卡/地图

  1. 没有错误或警告,如果一个关卡加载有任何错误或警告,应立即修复它们。
  2. 应构建光照,在进行测试/内部/运输构建或任何要分发的构建时,应始终构建光照。
  3. 关卡不应在玩家可见的所有区域中出现任何 z-fighting。

5. 市场特定规则

如果一个项目要在 UE4 Marketplace 上出售,它必须遵循这些规则。

  • 概述关卡(Overview)
    如果您的项目包含应可视化或演示的资产,则您的项目中必须有一个包含名称“Overview”的地图。
    如果是可视化资产,则此概览图应根据 Epic 的指南进行设置。
  • 演示关卡(Demo)
    关卡示例或附带某种教程的资产,则您的项目中必须有一个包含名称“Demo”的地图。此关卡还应包含以某种形式说明如何使用您的项目的文档。请参阅 Epic 的内容示例项目以获取有关如何执行此操作的良好示例。

6. 蓝图

  1. 所有蓝图都应以零警告和零错误进行编译。 如有问题,您应该立即修复蓝图警告和错误。不要忽视警告。
  2. 损坏的蓝图可能会导致以其他方式表现出来的问题,例如损坏的引用、意外行为、Cook失败和频繁的不必要的重新编译。 一个坏的蓝图有能力破坏你的整个游戏!!!
  3. 不要将损坏的蓝图提交给源代码控制。
  4. 蓝图风格
    1. 线条不要乱七八糟
    2. 对齐线条而不是节点
    3. 请始终拉直白色执行线
    4. 进行合理注释
    5. 转换可能出错的位置要有提示
    6. 不要有没目的、不执行的悬空节点

7. 变量

  1. 所有变量都应采用 PascalCase 的形式。

  2. 所有非布尔变量名称尽量是名词

  3. 所有布尔值都应以小写 b 为前缀,且尽量是形容词。
    不要带有 Is,Has,Can等提问前缀。这是为返回Bool的函数保留的。
    坏的命名 bIsDead、bIsHostile
    好的命名 bDead、bHostile
    尽量不要使用动词,例如 bRunning。动词带有复杂的状态,请使用枚举替换,且所有复杂的状态都应使用枚举替换。

  4. 所有变量命名不需要重复体现上下文关系,蓝图中的所有变量引用始终具有上下文关系。
    坏的命名 PlayerKills、MyCharacterName、ChosenCharacterSkin
    好的命名 Kills、Name、Skin
    所有这些变量都被冗余命名,来提示该变量属于 PlayerCharacter,但是通过上下文已经知道变量的主拥有者是 PlayerCharacter了。

  5. 变量命名不要包含基础类型名称
    好的命名 Score、Kills 、Description
    坏的命名 ScoreFloat、FloatKills、DescriptionString
    此规则的唯一例外是当变量表示要计算的“数量”,并且使用带变量类型的名称易阅读时。
    示例:围栏生成器需要生成 X 个柱子(Post)。将 X 存储在 PostsNum 或 PostsCount 中,而不是 Num,Count,因为 可能存在多个需要表示数量关系的变量。

  6. 变量命名包括非基础类型名称
    如果一个类拥有一个复杂变量的实例,即如果一个 BP_PlayerCharacter 拥有一个 BP_Hat,它应该被存储为变量类型,不要修改为其他名称。
    好的命名 Hat、Flag 、Ability
    坏的命名 MyHat、MyFlag 、PlayerAbility。

  7. 数组
    数组命名为复数名词,且遵循上述规则。
    好的命名 Targets、Hats、 EnemyPlayers
    坏的命名 TargetList、HatArray、EnemyPlayerArray。

  8. 可编辑变量
    所有不能安全更改或不应向设计人员公开的变量不应标记为可编辑。

  9. 分类
    如果一个类只有少量变量,可以使用默认类别。
    如果一个类具有中等数量的变量 (5-10),则所有可编辑变量都应分配一个非默认类别Config。
    如果一个类有大量的变量,那么所有可编辑变量都应该在 Config 类别下划分为出对应的子类别。
    所有不可编辑的变量应独立于Config创建描述其用途的类别。
    您可以使用管道字符 | 来定义子类别,即 Config | Animations。

  10. 私有变量
    如果知道一个变量只能在定义它的类中访问,请将变量标记为私有。不要轻易公开变量。

  11. 高级显示
    如果一个变量可编辑的,但通常不变,请将其标记为高级显示,这可以使得变量隐藏于详情面板,节省展示空间。

  12. 配置变量
    配置变量在 C++ 中用于具有较少更改率的变量。过多使用会使得设计师难以控制蓝图行为。

8. 函数、事件和事件分发器

  1. 函数命名的思考方向
    是纯函数吗?
    它是在获取状态信息吗?
    是处理程序吗?
    是 RPC 吗?
    它的目的是什么?
  2. 所有函数都应该是动词。
  3. 所有函数尽可都能用现在时来表达。
  4. 使用通知变量复制的所有函数都应具有 OnRep_Variable 的形式。这是由蓝图编辑器强制执行的。
  5. 编写一个不改变任何对象的状态或修改任何对象并且纯粹用于获取,计算,返回布尔值的函数时,应该提问,可以带有Is,Has,Can,Was前缀。
    好的命名
    IsVisible - 是否可见
    HasWeapon - 是否有武器,“有”是一个动词。
    WasCharging - 是否在充电,“Was”是“be”的过去式。
    CanReload - 是否可重新加载,“Can”是一个动词。
    坏的命名
    Fire - 着火了吗?还是开火吗?
    OnFire - 可能与用于触发的事件调度程序混淆。
    Dead - 死了吗?设置死亡?
    Visible - 获取可见吗?设置可见性?
  6. 事件处理程序和调度程序应以 On 开头并尽量遵循动词规则。
    有一些框架中用Handle来表示事件响应,但在虚幻中建议使用 On 代替 Handle
    好的命名
    OnDeath - 在死亡时;游戏中的常见搭配
    OnReceiveMessage - 在接收消息时
    OnTargetChanged - 在目标变更时
    OnClick - 在点击时
    坏的命名
    OnData - 在数据时
    OnTarget - 在目标时
    HandleMessage - 处理消息
    HandleDeath - 处理死亡
  7. 远程过程调用应以目标为前缀
    每次创建 RPC 时,它都应该以 Server、Client 或 Multicast 作为前缀。没有例外。
    好的命名
    ServerFireWeapon - 服务器中的开火武器
    ClientNotifyDeath - 客户通知死亡
    MulticastSpawnTracerEffect - 多播创建跟踪特效
    坏的命名
    FireWeapon - 不表示它是某种 RPC。
    ServerClientBroadcast - 令人困惑。
    AllNotifyDeath - 使用多播,而不是全部。
    ClientWeapon - 没有动词,模棱两可。
  8. 所有函数都必须有返回节点,没有例外。
  9. 任何函数都不应有超过 50 个节点
    任何过大的功能都应该分解成更小的功能。
    以下节点不计算在内,因为它们被认为不会增加功能复杂性:
    Comment - 注释
    Route - 变更路线节点
    Cast - 类型转换
    Getting a Variable - 获得一个变量
    Breaking a Struct - 分解一个结构体
    Function Entry - 函数入口
    Self - 自身
  10. 所有公共功能都应该有描述(Comment)
    以便 其他人 可以更轻松地理解和使用您的蓝图 API。
  11. 所有自定义静态插件的BlueprintCallable函数必须按插件名称分类
    例如,Zed Camera Interface 或 Zed Camera Interface | Image Capturing。
  • 9
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值