Giter VIP home page Giter VIP logo

ue4-style-guide's Introduction

元焏_UE4工程规范

元焏项目组UE4规范——初稿

目录

  1. 资源命名约定
  2. 目录结构
  3. 蓝图

专业术语

文件与目录的英文名

英文翻译标准以DeepL为唯一标准 他可能不是最好用的翻译软件,但一定是全世界最权威的自动翻译软件

关卡/地图(Levels/Maps)

“地图(map)”这个词通常也会被称为“关卡(level)”,两者的含义是等同的,在这里可以查看这个词的发展经历

贴图/纹理(texture)

无论是”贴图“还是"纹理"指的都是一个东西,英文名都叫做Texture

变量/属性(Variables / Properties)

'变量'和'属性'两个词在很多情况下是可以互相通用的。但如果他们同时出现在一个环境时,含义有一些不同:

属性(Property)

'属性'通常定义在一个类的内部。例如,如果一个类BP_Barrel有一个内部成员bExploded,那么bExploded可以是做是BP_Barrel的一个属性 当'属性'用在类的内部时,通常用来获取已经定义好的数据

变量(Variable)

'变量'通常用在给函数传递参数,或者用在函数内的局部变量 当'变量'用在类的内部时,通常是用来定义什么或者用来保存某些数据的。

命名法(Cases)

对于命名法有数种,以下是几种常见的方式,像UE4这样的复杂项目则需要将多种命名法组合使用

大驼峰命名法(PascalCase)

每个单词的首字母都是大写,单词之间没有其他字符,例如 :DesertEagle, StyleGuide, ASeriesOfWords

小驼峰命名法(camelCase)

第一个单词的首字母小写,后面的单词的首字母大写,例如:desertEagle, styleGuide, aSeriesOfWords

下划线命名法(Snake_case)

单词之间用下划线链接,单词的首字母可以大写也可以小写,例如:desert_Eagle, Style_Guide, a_Series_of_Words

关于命名方式详细介绍:文件夹命名

0. 原则

0.1 规范的遵守

对规范优劣的争论是没有意义的,有规范你就该去遵守。

规范不仅是用来命名文件的,也是用来进行快速沟通的,需要所有人记住规范(自己需要的部分)并使用,所以不存在自动生成文件命名规范的软件

项目规范应该是不断进步的,当你发现有好的更改时,你应该建议去更改现有规范

0.2 工程中所有的数据结构、资源、代码风格应该统一,如同是同一个人的作品

把资源从一个工程迁移到另一个工程不应该产生新的学习成本,所有资源应该符合项目规范,消除不必要的歧义和不确定性

遵守规范可以促进对于项目的生产和维护效率,因为团队成员不用去考虑规范问题,只需要去遵守。

本套规范根据诸多优秀经验编写,遵守它意味着可以少走很多弯路。

0.3 好哥们也得讲原则。

如果你发现周围有同学不遵守规范,你需要去纠正他,否则最后遭殃的可能是你自己

1. 资源命名约定 !

对于资源的命名的规范应该像法律一样被遵守。一个项目如果有好的命名规范,那么在资源管理、查找、解析、维护时,都会有极大的便利性。

大多数资源的命名都应该有前缀,前缀一般是资源类型的缩写,然后使用下划线和资源名链接。

1.1 基本命名规则 Prefix_BaseAssetName_Variant_Suffix !

时刻记住这个命名规范Prefix_BaseAssetName_Variant_Suffix,只要遵守它,大部分情况下都可以让命名规范。下面是详细的解释。

Prefix(前缀) 和 Suffix(后缀)由资源类型确定,请参照下面的资源类型表

所有资源都应该有一个BaseAssetName(基本资源名)。所谓基本资源名表明该资源在逻辑关系上属于那种资源,任何属于该逻辑组的资源都应该遵守同样的命名规范

基本资源名应该使用简短而便于识别的词汇,例如,如果你有一个角色名字叫做Bob,那么所有和Bob相关的资源的BaseAssetName都应该叫做Bob

Varient(扩展名)用来保证资源的唯一性,同样,扩展名也应该是简短而容易理解的短词,以说明该资源在所属的资源逻辑组中的子集。例如,如果Bob有多套皮肤,那么这些皮肤资源都应该使用Bob作为基本资源名同时包含扩展名,例如'Evil'类型的皮肤资源,名字应该是Bob_Evil,而Retro类型的皮肤应该是用Bob_Retro

一般来说,如果仅仅是为了保证资源的唯一性,Varient可以使用从01开始的两位数字来表示。例如,如果你要制作一堆环境中使用的石头资源,那么他们应该命名为Rock_01, Rock_02, Rock_03等等。除非特殊需要,不要让数字超过三位数,如果你真的需要超过100个的资源序列,那么你应该考虑使用多个基础资源名

基于你所制作的资源扩展属性,你可以把多个扩展名串联起来。例如,如果你在制作一套地板所使用的资源,那么你的资源除了使用Flooring作为基本名,扩展名可以使用多个,例如Flooring_Marble_01, Flooring_Maple_01, Flooring_Tile_Squares_01

1.1 范例

1.1e1 Bob
资源类型 资源名
骨骼模型(Skeletal Mesh) SK_Bob
材质(Material) M_Bob
反射贴图(Texture (Diffuse/Albedo)) T_Bob_D
法线贴图(Texture (Normal)) T_Bob_N
1.1e2 石头(Rocks)
资源类型 资源名
静态网格01(Static Mesh (01)) S_Rock_01
静态网格02(Static Mesh (02)) S_Rock_02
静态网格03(Static Mesh (03)) S_Rock_03
材质(Material) M_Rock
材质实例(Material Instance (Snow)) MI_Rock_Snow

1.2 资源类型表 !

当给一个资源命名的时候,请参照以下表格来决定在资本资源名前后所使用的前缀和后缀

目录

1.2.1 常用类型(Most Common)

1.2.2 动作(Animations)

1.2.3 人工智能(Artificial Intelligence)

1.2.4 蓝图(Blueprints)

1.2.5 材质(Materials)

1.2.6 纹理(Textures)

1.2.7 杂项(Miscellaneous)

1.2.8 Paper2D

1.2.9 物理(Physics)

1.2.10 声音(Sound)

1.2.11 用户界面(User Interface)

1.2.12 特效(Effects)

1.2.1 常用类型 !

资源类型 前缀 后缀 备注
关卡(Level / Map) 所有地图应该放在Maps目录下
主关卡(Level (Persistent)) _P
音效关卡(Level (Audio)) _Audio
光照关卡(Level (Lighting)) _Lighting
体积关卡(Level (Geometry)) _Geo
逻辑关卡(Level (Gameplay)) _Gameplay
蓝图(Blueprint) BP_
材质(Material) M_
静态模型(Static Mesh) SM_
骨骼模型(Skeletal Mesh) SK_
图片/纹理/贴图(Texture) T_ _? 参照纹理
粒子系统(Particle System) PS_
UI/控件蓝图(Widget Blueprint) WB_ WB_.

1.2.2 动画

资源类型 前缀 后缀 备注
瞄准偏移(Aim Offset) AO_
瞄准偏移1D(Aim Offset 1D) AO_
动画蓝图(Animation Blueprint) ABP_
动画合成(Animation Composite) AC_
动画蒙太奇(Animation Montage) AM_
动画序列(Animation Sequence) AS_
混合空间(Blend Space) BS_
混合空间1D(Blend Space 1D) BS_
关卡序列(Level Sequence) LS_
变形目标(Morph Target) MT_
Rig Rig_
骨骼模型(Skeletal Mesh) SK_
骨骼(Skeleton) SKEL_

对于一般动画命名之后会讨论

1.2.3 人工智能(AI) !

资源类型 前缀 后缀 备注
AI控制器(AI Controller) AIC_
行为树(Behavior Tree) BT_
黑板(Blackboard) BB_
装饰器(Decorator) BTDecorator_
服务器(Service) BTService_
任务(Task) BTTask_

1.2.4 蓝图 !

资源类型 前缀 后缀 备注
蓝图(Blueprint) BP_
蓝图函数库(Blueprint Function Library) BPL_
蓝图接口(Blueprint Interface) BPI_
蓝图宏库(Blueprint Macro Library) BPML_ 可能的话尽量不要使用蓝图宏
枚举(Enumeration) E 没有下划线
结构体(Structure) F 没有下划线
用于建表的结构体(Structure) FST_
UI/控件蓝图(Widget Blueprint) WB_

1.2.5 材质 !

资源类型 前缀 后缀 备注
材质(Material) M_
后期处理材质(Material (Post Process)) PP_
材质函数(Material Function) MF_
材质引用(Material Instance) MI_
材质参数集合(Material Parameter Collection) MPC_
次表面描述文件(Subsurface Profile) SP_
物理材质(Physical Materials) PM_

1.2.6 贴图/纹理(Texture) !

以下内容默认 贴图=纹理 蒙版=遮罩,仅仅是不同地方叫法不同,推荐使用贴图、遮罩描述

资源类型 前缀 后缀 备注
贴图(Texture) T_
基础颜色纹理(Texture (Base Color) T_ _D
反射贴图(Texture (Diffuse/Albedo/Base Color)) T_ _D
法线贴图(Texture (Normal)) T_ _N
粗糙度贴图(Texture (Roughness)) T_ _R
透明贴图(Texture (Alpha/Opacity)) T_ _A
环境光遮罩/蒙板贴图(Texture (Ambient Occlusion)) T_ _AO
自发光贴图(Texture (Emissive)) T_ _E
这招贴图(Texture (Mask)) T_ _M
反射贴图(Texture (Specular)) T_ _S
已打包纹理(Texture (Packed)) T_ _* 参见下面的纹理打包备注.
体积纹理(Texture Cube) TC_
媒体纹理(Media Texture) MT_
渲染目标(Render Target) RT_
立方体渲染目标(Cube Render Target) RTC_
光照描述贴图(Texture Light Profile) TLP

<a name="anc-textures-packing"

1.2.6.1 贴图合并 !

把多张贴图存于一个贴图文件中是很常见的方法,比如通常可以把自发光(Emissive), 粗糙度(Roughness), 环境光(Ambient Occlusion)以RGB通道的形式保存在贴图中,然后在文件的后缀中,注明这些信息,例如_EGO

一般来说,在纹理的Diffuse信息中附带Alpha/Opacity信息是很常见的,这时在_D后缀中加入A

不推荐同时把RGBA四个通道的信息保存在一张纹理中,这是由于带有Alpha通道的纹理要比不带的占用更多的资源,除非Alpha信息是以遮罩/蒙版(Mask)的形式保存在Diffuse/Albedo通道中。

1.2.7 杂项 !

资源类型 前缀 后缀 备注
动画向量场(Animated Vector Field) VFA_
相机动画(Camera Anim) CA_
颜色曲线(Color Curve) Curve_ _Color
曲线表格(Curve Table) Curve_ _Table
数据资产(Data Asset) *_ 前缀取决于何种类型资源
数据表格(Data Table) DT_
曲线(Float Curve) Curve_ _Float
草地地形类型(Landscape Grass Type) LG_
地形层(Landscape Layer) LL_
Matinee数据(Matinee Data) Matinee_
媒体播放器(Media Player) MP_
对象库(Object Library) OL_
静态矢量场(Static Vector Field) VF_
向量曲线(Vector Curve) Curve_ _Vector

1.2.8 2D !

资源类型 前缀 后缀 备注
Paper图像序列(Paper Flipbook) PFB_
Sprite SPR_
Sprite Atlas Group SPRG_
瓦片地图/映射(Tile Map) TM_
瓦片集合(Tile Set) TS_

1.2.9 物理 !

资源类型 前缀 后缀 备注
物理材质(Physical Material) PM_
物理资产(Physical Asset) PHYS_
可破坏网格(Destructible Mesh) DM_

1.2.10 音效 !

资源类型 前缀 后缀 备注
对话音效(Dialogue Voice) DV_
对话音波(Dialogue Wave) DW_
媒体音效(Media Sound Wave) MSW_
混响效果(Reverb Effect) Reverb_
音效衰减(Sound Attenuation) ATT_
音效类(Sound Class) 没有前缀和后缀,这些资源应该放在SoundClasses目录中
音效并发(Sound Concurrency) _SC 在SoundClass之后命名
Sound Cue A_ _Cue
音效混合(Sound Mix) Mix_
音波(Sound Wave) A_

1.2.11 用户界面/UI !

资源类型 前缀 后缀 备注
字体(Font) Font_
Slate笔刷(Slate Brush) Brush_
Slate控件样式(Slate Widget Style) Style_
控件蓝图(Widget Blueprint) WB_

1.2.12 粒子效果FX(Effects) !

Asset Type Prefix Suffix Notes
粒子系统(Particle System) PS_
后处理材质(Material (Post Process)) PP_
Niagara N_

2. 目录结构 !

对资源目录的规范管理和资源文件同等重要,都应该像法律一样被严格遵守。不规范的目录结构会导致严重的混乱。

在本套规范中,我们尽量利用了UE4的资源浏览器的过滤和搜索功能来查找资源,而不是按照资源类型来划分目录结构。

2e1 目录结构示例

|-- Content
    |-- YuanQi
        |-- Art
        |   |-- Industrial
        |   |   |-- Ambient
        |   |   |-- Machinery
        |   |   |-- Pipes
        |   |-- Nature
        |   |   |-- Ambient
        |   |   |-- Foliage
        |   |   |-- Rocks
        |   |   |-- Trees
        |   |-- Office
        |-- Characters
        |   |-- Bob
        |   |-- Common
        |   |   |-- Animations
        |   |   |-- Audio
        |   |-- Jack
        |   |-- Steve
        |   |-- Zoe
        |-- Core
        |   |-- Characters
        |   |-- Engine
        |   |-- GameModes
        |   |-- Interactables
        |   |-- Pickups
        |   |-- Weapons
        |-- Effects
        |   |-- Electrical
        |   |-- Fire
        |   |-- Weather
        |-- Maps
        |   |-- Campaign1
        |   |-- Campaign2
        |-- MaterialLibrary
        |   |-- Debug
        |   |-- Metal
        |   |-- Paint
        |   |-- Utility
        |   |-- Weathering
        |-- Placeables
        |   |-- Pickups
        |-- Weapons
            |-- Common
            |-- Pistols
            |   |-- DesertEagle
            |   |-- RocketPistol
            |-- Rifles

使用这种目录结构的原因列在下面

目录

2.1 文件夹命名(Folder Names)

2.2 顶层目录(Top-Level Folders)

2.3 开发者目录(Developer Folders)

2.4 地图目录(Maps)

2.5 核心资源(Core)

2.6 避免以AssetsAssetTypes命名

2.7 超大资源(Large Sets)

2.8 材质库(Material Library)

2.1 文件夹命名 !

关于文件夹的命名,有一些通用的规范

2.1.1 使用大驼峰命名法(PascalCase)大小写规范* !

文件夹的命名需要遵守大驼峰命名法规范,也就是所有单词的首字母大写,并且中间没有任何连接符。例如DesertEagle, RocketPistol, and ASeriesOfWords.

参照大小写规范.

2.1.3 不要使用包括中文、空格在内的奇怪的符号 !

永远永远永远在目录名中只使用`a-z`大小写 `0-9`这两类安全的字符,
如果你使用了类似于`元`,`焏`,`@`, `-`, `_`, `,`, `*`, 或者 `#`这样的字符,难免会碰到一些操作系统、源码管理工具或者一些弱智的工具不支持。
同样,也不要把本地工程放在包含有其他符号的目录下面,应该放在类似于`D:\Project`这样的目录里,而不是`C:\Users\My Name\My Documents\Unreal_Projects\元焏`这样的目录。

2.2 使用一个顶级目录来保存所有工程资源 !

所有的工程资源都应该保存在一个以工程名命名的目录中。例如工程叫做'YuanQi',那么所有该工程的资源都应该保存在Content/YuanQi目录中。

开发者目录Developers不用受此限制,参照下面的开发者目录中的详细说明。

使用顶级目录的原因有如下。

2.2.1 避免全局资源

通常在代码规范中会警告你不要使用全局变量以避免污染全局命名空间。基于同样的道理,不存在于工程目录中的资源对于资源管理会造成不必要的干扰。

每个属于项目资源都应该有它存在的目的。如果仅仅是为了测试或者体验而使用的资源,那么这些资源应该放在开发者目录中。

2.2.2 减少资源迁移时的冲突

当一个团队有多个项目时,从一个项目中把资源拷贝到另一个项目会非常频繁,这时最方便的方法就是使用引擎的资源浏览器提供的Migrate功能,因为这个功能会把资源的依赖项一起拷贝到目标项目中。

这些依赖项经常造成麻烦。如果两个工程没有项目顶级目录,那么这些依赖项很容易就会被拷贝过来的同名资源覆盖掉,从而造成意外的更改。

这也是为什么EPIC会强制要求商城中出售的资源要遵守同样的规定的原因

执行完Migrate资源拷贝后,安全的资源合并方法是使用资源浏览器中的'替换引用'(Replace References)工具,把不属于工程目录中的资源引用替换掉。一旦资源资源完成完整的合并流程,工程目录中不应该存在另一个工程的顶级目录。这种方法可以_100%_保证资源合并的安全性。

2.2.3 范例,模板以及商场中的资源都是安全没有风险的

正如2.2.2所讲,如果你想把官方范例、模板以及商城中购买的资源放到自己的工程中,那么这些资源都是可以保证不会干扰现有工程的,除非你购买的资源工程和你的工程同名。

当然也不能完全信任商城上的资源能够完全遵守顶级目录规则

2.2.4 容易维护DLC、子工程、以及补丁包

如果工程开发DLC或者子工程,那么这些子工程所需要的资源应该迁移出来放在另一个顶级目录中,这样的结构使得编译这些版本时可以区别对待子工程中的资源。子工程中的资源的迁入和迁出代价也更小。如果想在子项目中修改一些原有工程中的资源,那么可以把这些资源迁移到子工程目录中,这样不会破坏原有工程。

2.3 用来做临时测试的开发者目录 !

在一个项目的开发期间,团队成员经常会有一个'沙箱'目录用来做测试而不会影响到工程本身。因为工作是连续的,所以即使这些'沙箱'目录也需要进行源码版本控制。但并不是所有成员都需要这种开发者目录的,但使用开发者目录的成员来说,一旦这些目录是在服务器上管理的,总会需要一些麻烦事。

首先团队成员极容易使用这些尚未准备好的资源,这些资源一旦被删除就会引发问题。例如一个做模型的美术正在调整一个模型资源,这时一个做场景编辑的美术如果在场景中使用了这个模型,那么很可能会导致莫名其妙的问题,进而造成大量的工作浪费。

但如果这些模型放在开发者目录中,那么场景美术人员就没有任何理由使用这些资源。UE4资源浏览器的默认设置会自动过滤掉这个目录,从而保证正常情况下不可能出现被误用的情况。

一旦这些资源真正准备好,那么美术人员应该把它们移到正式的工程目录中并修复引用关系,这实际上是让资源从实验阶段'推进'到了生产阶段。

2.4 所有的地图*文件应该保存在'Maps'的目录中 !

无论如何你都应该把所有地图保存在/Content/YuanQi/Maps

通过子目录的方法去组织地图资源,避免子关卡的错误加载,例如建立 Maps/StartMap/(开始关卡) 和 'Maps/PlayMap`(游玩关卡)

这有助于产品的打版本工作,如果工程里的地图保存的到处都是,版本升级时还要到处去找,就让人很恼火了,而把地图放在一个地方,做版本时就很难漏掉某个地图,对于烘培光照贴图或者质量检查都有利。

2.5 使用Core目录存储系统蓝图资源以及其他系统资源 !

使用/Content/Project/Core这个目录用来保存一个工程中最为核心的资源。 例如,游戏模式(GameMode), 角色(Character), 玩家控制器(PlayerController), 游戏状态(GameState), 玩家状态(PlayerState),以及如此相关的一些资源也应该放在这里。

非程序员不要去碰这个目录,策划也只需要使用子类提供的功能就可以工作,负责场景编辑的员工只需要使用专用的的蓝图就可以,而不用碰到这些基础类。

例如,如果项目需要设计一种可以放置在场景中并且可以被捡起的物体,那么应该首先设计一个具有被捡起功能的基类放在Core/Pickups目录中,而各种具体的可以被捡起的物体诸如药瓶、子弹这样的物体,应该放在/Content/Project/Placeables/Pickups/这样的目录中。游戏设计师可以在这些目录中定义和设计这些物体,所以其他人不需要也不应该去碰Core/Pickups目录下的代码,要不然可能无意中破坏工程中的其他功能

2.6 不要创建名为Assets 或者 AssetTypes的目录 !

2.6.1 创建一个名为Assets的目录是多余的。 !

因为本来所有目录就是用来保存资源的

2.6.2 创建名为MeshesTextures或者Materials的目录是多余的。 !

资源的文件名本身已经提供了资源类型信息,所以在目录名中再提供资源类型信息就是多余了,而且使用资源浏览器的过滤功能,可以非常便利的提供相同的功能。

比如想查看Environment/Rocks/目录下所有的静态Mesh资源?只要打开静态Mesh过滤器就可以了,如果所有资源的文件名已经正确命名,这些文件还会按照文件名和前缀正确排序,如果想查看所有静态Mesh和带有骨骼的Mesh资源,只要打开这两个过滤器就可以了,这种方法要比通过打开关闭文件夹省事多了。

这种方法也能够节省路径长度,因为用前缀S_只有两个字符,要比使用Meshes/七个字符短多了。

这么做其实也能防止有人把Mesh或者纹理放在Materials目录这种愚蠢行为。

2.7 对于动画和声音资源应该有自己的目录结构 !

这节可以视为针对2.6的补充

对于动画资源和声音资源这一欸数量巨大,而且每个作用都不同的资源。如果你发现有15个以上的资源属于同一个逻辑类型,那么它们应该被放在一起。

举例来说,角色共用的动画资源应该放在Characters/Common/Animations目录中,并且其中应该还有诸如Locomotion 或者Cinematic的子目录

2.8 材质库MaterialLibrary !

如果你的工程中使用了任何基础材质、分层材质,或者任何被重复使用而不属于特定模型的材质和纹理,这些资源应该放在材质库目录Content/Project/MaterialLibrary

这样可以很容易管理这些'全局'材质

这也使得'只是用材质实例'这个原则得以执行的比较容易。如果所有的美术人员都只是用材质实例,那么所有的原始材质都应该保存在这个目录中。你可以通过搜索所有不在MaterialLibrary中的基础材质来验证这一点。

MaterialLibrary这个目录并不是仅能保存材质资源,一些共用的工具纹理、材质函数以及其他具有类似属性的资源都应该放在这个目录或子目录中。例如,噪点贴图应该保存在MaterialLibrary/Utility目录中。

任何用来测试或调试的材质应该保存在MaterialLibrary/Debug中,这样当工程正式发布时,可以很容易把这些材质从删除,因为这些材质如果不删除,可能在最终产品中非常扎眼。

3. 蓝图 !

这一章会专注于蓝图和蓝图的实现。如果可能的话,本规则和Epic官方提供的标准一致。

目录

3.1 编译(Compiling)

3.2 变量(Variables)

3.3 函数(Functions)

3.4 图形节点(Graphs)

3.1 编译 !

需要保证所有蓝图在编译时0警告和0错误。应该尽快修复所有警告和异常,以免它们造成可怕的麻烦。

绝对不要提交那些断开的蓝图,如果你需要通过源码服务器保存,那么必须暂时搁置它们

断开的蓝图有巨大的破坏力,而且会在蓝图之外展现威力,比如造成引用失效,未定义的行为,烘培失败,或者频繁的重新编译。一个断开的蓝图可能会毁掉整个项目。

3.2 变量 !

变量(variable)和属性(property)这两个词经常是可以互换的。

目录

3.2.1 命名(Naming)

3.2.2 可编辑行(Editable)

3.2.3 分类(Categories)

3.2.4 权限(Access)

3.2.5 高级(Advanced)

3.2.6 临时变量(Transient)

3.2.7 游戏存档(SaveGame)

3.2.8 配置(Config)

3.2.1 命名规范 !

3.2.1.1 使用名词 !

所有非布尔类型的变量必须使用简短、清晰并且意义明确的名词作为变量名。

3.2.1.2 大驼峰命名法(PascalCase) !

所有非布尔类型的变量的大小写需要遵守大驼峰命名法(PascalCase)规则。

3.2.1.2e 范例:
  • Score
  • Kills
  • TargetPlayer
  • Range
  • CrosshairColor
  • AbilityID

3.2.1.3 布尔变量需要前缀 b !

所有布尔类型变量需要遵守大驼峰命名法(PascalCase)规则,但前面需要增加小写的b做前缀。

例如: 用 bDeadbEvil, 不要 使用DeadEvil.

UE4的蓝图编辑器在显示变量名称时,会自动把前缀b去掉

3.2.1.4 布尔类型变量命名规则 !

3.2.1.4.1 一般的独立信息 !

布尔类型变量如果用来表示一般的信息,名字应该使用描述性的单词,不要包含具有提问含义的词汇,比如Is,这个词是保留单词。

例如:使用bDead and bHostile不要使用bIsDead and bIsHostile

也不要使用类似于bRunning这样的动词,动词会让含义变得复杂

3.2.1.4.2 复杂状态 !

不要使用布尔变量保存复杂的,或者需要依赖其他属性的状态信息,这会让状态变得复杂和难以理解,如果需要尽量使用枚举来代替。

例如:当定义一个武器时,不要使用bReloadingbEquipping这样的变量,因为一把武器不可能即在reloading状态又在equipping状态,所以应该使用定义一个叫做EWeaponState的枚举,然后用一个枚举变量WeaponState来代替,这也使得以后增加新的状态更加容易。

例如:不要使用bRunning这样的变量,因为你以后有可能还会增加bWalking 或者 bSprinting,这也应该使用一个枚举来非常清晰的定义这样的状态。

3.2.1.5 考虑上下文 !

蓝图中的变量命名时需要考虑上下文环境,避免重复不必要的定义。

3.2.1.5e 例如:

假设有一个蓝图名为 BP_PlayerCharacter.

不好的命名

  • PlayerScore
  • PlayerKills
  • MyTargetPlayer
  • MyCharacterName
  • CharacterSkills
  • ChosenCharacterSkin

这些变量的命名都很臃肿。因为这些变量都是属于一个角色蓝图BP_PlayerCharacter的,没必要在变量中再重复这一点。

好的命名

  • Score
  • Kills
  • TargetPlayer
  • Name
  • Skills
  • Skin

3.2.1.6 不要在变量中包含原生变量类型名 !

所谓原生变量是指那些最简单的保存数据的变量类型,比如布尔类型、整数、浮点数以及枚举。

字符串(String)和数组(vectors)在蓝图中也属于原生变量类型,但严格来讲它们其实不是。

由三个浮点数组成的vector经常被视为一个整体数据类型,比如旋转向量。

文本类型变量(Text)不属于原生类型,因为它们内部还包含有国际化信息。原生类型的字符串变量类型是String , 而不是Text

原生类型的变量名中不应该包含变量类型名。

例如:使用Score, Kills, 以及 Description不要使用ScoreFloat, FloatKills, DescriptionString

但也有例外情况,当变量的含义包含了"多少个"这样的信息,并且仅用一个名字无法清晰的表达出这个含义时。

比如:游戏中一个围墙生成器,需要有一个变量保存在X轴上的生成数量,那么需要使用NumPosts 或者 PostsCount这样的变量,因为仅仅使用Posts可能被误解为某个保存Post的数组

3.2.1.7 非原生类型的变量,需要包含变量类型名 !

非原生类型的变量是指那些通过数据结构保存一批原生类型的复杂变量类型,比如结构体(Structs)、类(Classes)、接口(Interface),还有一些有类似行为的原生变量比如文字(Text)名字(Name)也属于此列。

如果仅仅是原生变量组成的数组,那么这个数组仍然属于原生类型

这些变量的名字应该包含数据类型名,但同时要考虑不要重复上下文。

如果一个类中包拥有一个复杂变量的实例,比如一个BP_PlayerCharacter中有另一个变量BP_Hat,那么这个变量的名字就不需要包含变量类型了。

例如: 使用 HatFlag以及 Ability不要使用MyHatMyFlagPlayerAbility

但是,如果一个类并不拥有这个属性,那么就需要在这个属性的名字中包含有类型的名字了

例如:一个蓝图类BP_Turret用来顶一个炮塔,它拥有瞄准BP_PlayerCharacter作为目标的能力,那么它内部会保存一个变量作为目标,名字应该是TargetPlayer,这个名字非常清楚的指明了这个变量的数据类型是什么。

3.2.1.8 数组 !

数组的命名规则通常和所包含的元素的规则一样,但注意要用复数。

例如:用TargetsHats以及 EnemyPlayers不要使用TargetListHatArray 或者 EnemyPlayerArray

3.2.2 可编辑变量 !

所有可以安全的更改数据内容的变量都需要被标记为Editable

相反,所有不能更改或者不能暴露给设计师的变量都不能表上可编辑标志,除非因为引擎的原因,这些变量需要被标为Expose On Spawn

总之不要轻易使用Editable标记

3.2.2.1 Tooltips !

对于所有标记为Editable的变量,包括被标记为 Expose On Spawn的变量,都应该在其Tooltip内填写关于如何改变变量值,以及会产生何种效果的说明。

3.2.2.2 滑动条(Slider)以及取值范围 !

对于可编辑的变量,如果不适合直接输入具体数值,那么应该通过一个滑动条(Slider)并且加上取值范围来让设计师输入。

举例:一个产生围墙的蓝图,拥有一个PostsCount的变量,那么-1显然适合不合理的输入,所以需要设上取值范围注明0是最小值

如果在构造脚本中需要一个可编辑变量,那么一定要首先定义一个合理的取值范围,要不然可能会有人设上一个非常大的值造成编辑器崩溃。

一个变量的取值范围只有当明确知道其范围时才需要定义,因为滑块的取值范围的确能够阻止用户输入危险数值,但用户仍然能够通过手动输入的方式输入一个超出滑块范围的值给变量,如果变量的取值范围未定义,那么这个值就会变得'很危险'但还是在合理的。

3.2.3 分类 !

如果一个类的变量很少,那么没有必要使用分类

如果一个类的变量规模达到中等(5-10),那么所有可编辑的变量应该自己的分类,而不应该放在缺省分类中,通常叫做 Config

如果类中的变量的数量非常大,那么所有可编辑的变量都应该放在Config分类的子分类下,所有不可编辑的变量应该根据它们的用途建立相关分类保存

通过在分类名中添加字符|,你可以直接建立子分类,比如Config | Animations

举例:一个武器的类中的变量分类目录大致如下:

|-- Config
|	|-- Animations
|	|-- Effects
|	|-- Audio
|	|-- Recoil
|	|-- Timings
|-- Animations
|-- State
|-- Visuals

3.2.4 变量的访问权限 !

在C++中,变量的访问类型由类成员的属性决定,Public类型的表示其他类都可以访问,Protetced类型的成员表示子类可以访问,Private类型变量表示只有类内部函数可以访问此变量。

蓝图并没有类似的权限访问设计。

就是视可编辑类型的变量作为Public类型变量,视不可编辑的变量作为Protected类型变量。

3.2.4.1 私有变量 !

尽量不要把变量生命为private类型,除非变量一开始就打算永远被类内部访问,并且类本身也没打算被继承。尽量用protected,private类型用在当你有非常清楚的理由要去限制子类的能力。

3.2.5 高级显示 !

如果一个变量可以被编辑,但通常不会有人碰到,那么就把它标记为高级显示Advanced Display。这些变量在蓝图中会缺省隐藏,除非点击节点上的高级显示箭头。

有意思的是,Advanced Display这个选项本身,在编辑器的变量属性中也是一个高级显示类型的。

3.2.6 Transient 变量 !

Transient类型的变量是指那些不需要被序列化(保存或者加载),并且初始值为0或者null的变量。一般用在引用其他对象,它们的值只有在运行时才知道。这样做能防止编辑器在磁盘上多存储一份多余的数据,以加快蓝图的存盘和加载速度。

因此,所有Transient类型变量都应该被初始化成0或者null。如果是其他值会增加调试bug的时候的难度。

3.2.7 SaveGame变量 !

绝对不要SaveGameTransient同时使用,这是明显不合理的。

3.2.8 Config变量 !

不要使用Config Variable这个标记,这会让设计师在控制蓝图行为上更加困难。这个标记一般用在C++中,用来标记那些极少被改变的变量,你可以认为它们是那些被标上Advanced Display的变量

3.3 函数、事件以及事件分发器 !

这一节用来解释应该如何管理函数、事件以及事件分发器。除非特殊说明,所有适用于函数的规则,同样适用于事件。

3.3.1 函数命名

对于函数、事件以及事件分发器的命名极其重要,仅仅从一个名字本身,就有很多条件要考虑,比如说:

  • 是纯虚函数吗??
  • 是状态查询函数吗?
  • 是事件相应函数吗?
  • 是远程调用函数吗?
  • 函数的目的是什么?

如果命名得当,这些问题甚至更多问题的答案会在名字中体现出来。

3.3.1.1 所有函数的命名都应该是动词

所有函数和事件执行者都是需要做一些动作,可能是去获取信息,也可能是数据计算,或者搞点什么事情。因此,所有函数都应该用动词开始,并且用一般现代时态,并且有上下文来表明它们究竟在做什么

OnRep 这样的相应函数,事件具柄和事件派发器的命名不遵守这个规则。

好的例子:

  • Fire - 如果类是一个角色或者武器,那么这是一个好命名,如果是木桶,玻璃,那这个函数就会让人困惑了。
  • Jump - 如果类是一个角色,那么这是个好名字,如果不是,那么需要一些上下文来解释这个函数的含义
  • Explode
  • ReceiveMessage
  • SortPlayerArray
  • GetArmOffset
  • GetCoordinates
  • UpdateTransforms
  • EnableBigHeadMode
  • IsEnemy - "Is" 是个动词

不好的例子:

  • Dead - 是已经死了?还是死的动作?
  • Rock
  • ProcessData - 无意义,这个名字等于没说.
  • PlayerState - 不能用名词
  • Color - 如果是动词,那么缺少上下文,如果是名词,也不行.

3.3.1.2 属性的状态变化响应函数应该命名为OnRep_Variable

所有用来响应状态变化的函数应该用OnRep_Variable的形式,这是由蓝图编辑器强制规定的,如果在C++中写OnRep函数,应该同样遵守这个规则。

3.3.1.3 返回布尔变量的信息查询函数应该是问询函数

如果一个函数不改变类的状态,并且只是返回信息、状态或者计算返回给调用者yes/no,这应该是一个问询函数。同样遵守动词规则

非常重要的是,应该假定这样的函数其实就是执行某种动作,并且返回动作是否执行成功。

好的例子:

坏的例子:

  • Fire - 是查询正在开火?还是查询能不能开火?
  • OnFire - 有可能和事件派发器函数混淆
  • Dead - 是查询已经死亡?还是查询会不会死亡?
  • Visibility - 是查询可见状态?还是设置可见状态?

3.3.1.4 事件的响应函数和派发函数都应该以On开头

事件的响应函数和派发函数都应该以On开头,然后遵守动词规则,如果是过去式,那么动词应该移到最后以方便阅读

在遵守动词规则的时候,需要优先考虑英语中的固定句式

好的例子:

  • OnDeath - 游戏中非常常见
  • OnPickup
  • OnReceiveMessage
  • OnMessageRecieved
  • OnTargetChanged
  • OnClick
  • OnLeave

坏的例子:

  • OnData
  • OnTarget
  • HandleMessage
  • HandleDeath

3.3.1.5 远程调用函数应该用目标作为前缀

任何时候创建RPC函数,都应该把目标作为前缀放在前面,例如ServerClient或者 Multicast,没有例外。

前缀之后的部分,遵守上面的其他规则。

好的例子:

  • ServerFireWeapon
  • ClientNotifyDeath
  • MulticastSpawnTracerEffect

坏的例子:

  • FireWeapon - 没有使用目标前缀
  • ServerClientBroadcast - 混淆.
  • AllNotifyDeath - 用 Multicast, 不要用 All.
  • ClientWeapon - 没有用动词, 让人困惑.

3.3.2 所有函数内部都应该在结束的地方有返回节点

所有函数内部都应该在结束的地方有返回节点,没有例外。

返回节点明确标注了蓝图到此执行完毕。蓝图中的结构有可能有并行结构Sequence、循环结构ForLoopWithBreak或者逆向的回流节点组成,明确结束节点使蓝图易于阅读维护和调试。

如果启用了返回节点,当你的蓝图中有分支没有正常返回,或者流程有问题,蓝图的编译器会提出警告。

比如说,有程序员在并行序列中添加了一个新的分支,或者在循环体外添加逻辑但没有考虑到循环中的意外返回,那么这些情况都会造成蓝图的执行序列出现意外。蓝图编译器会立即给这些情况提出警告。

3.3.3 蓝图函数中节点数不应该超过50个

简单来说,蓝图函数中的节点数应该小于50个,如果函数过于复杂,应该把它分割成几个小一点的函数,以便更好的阅读和维护。

3.4 蓝图图形

本节包含了关于蓝图图形的内容 This section covers things that apply to all Blueprint graphs.

3.4.1 不要在蓝图上画画!!!

蓝图中所有连线都应该有清晰的开始点和结束点。你的蓝图让阅读者在一堆乱糟糟的线中翻来翻去。 以下内容帮助你避免龙飞凤舞蓝图产生。

3.4.2 保持连线对齐,而不是节点

不要试图让节点对齐,对齐的应该是连线。你无法控制一个节点的大小和上面连接点的位置,但你能通过控制节点的位置来控制连线。笔直的连线让整个蓝图清晰美观,歪歪扭扭的连线会让蓝图丑陋不堪。你可以通过蓝图编辑器提供的功能直接让连线变直,方法是选择好节点,用快捷键Q

好的例子: 所有上面的节点的执行线都保持为直线。 Aligned By Wires

不好的例子: 右上角节点的执行线歪了 Bad

可接受的例子: 有些节点无论你怎么用对齐工具都无法对齐,这种情况下,就尽量缩短它们之间连线的长度。 Acceptable

3.4.3 白色的可执行线优先级最高

如果发现白色执行线和其他数据线无法同时对齐,白色执行线的优先级更高。

参考文档:

1.Airbnb的JS规范 Airbnb Javascript Style Guide

1.thejinchao翻译的ue4-style-guide[https://github.com/skylens-inc/ue4-style-guide]

1.UE4官方代码规范CodingStandard

⬆ 回到最顶端

ue4-style-guide's People

Contributors

allar avatar cnwenzhihong avatar skylens-inc avatar cosmomyzrailgorynych avatar schultzcole avatar thejinchao avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.