Unity 游戏框架:命名的力量--变量

简介:

Unity 游戏框架:命名的力量--变量
变量的命名入门
大家先来试着理解一下这段代码:

var todoList = new TodoList();
todoList.Todos = new List();

var todo = new Todo() { Id = 0, Finished = false, Content = "测试" };

todoList.Todos.Add(todo)

todo.Finished = true;
代码本身很简单,就算不用去看 TodoList 类和 Todo 类的定义,也是可以读懂以上代码的。

那这是如何做到的呢?

答案就是:进行合适的命名。

而达到以上代码的效果的主要是变量的命名。

因为以上出现的类都是 Model 类,而 Model 则是用来描述业务是什么,而 Model 类中大部分代码则是变量。
比如 这是一个 TodoList App (待办事项),其中:

有待办事项列表
待办事项列表有待办事项
待办事项可以完成和未完成。
待办事项可以编辑文本。
以上几点一般是我们接收到任务并理解业务之后梳理出来的。如果设计成代码结构,结构大致如下:

待办事项列表
待办事项
完成/未完成
文本
很自然 Model 的代码就写出来了,代码如下。

TodoList.cs

public class TodoList
{

public List<Todo> Todos;

}
Todo.cs

public class Todo
{

public int Id;

public bool Finished;

public string Content;

}
为了让以上类更容易地在其他文件中理解,笔者在命名上做了哪些工作呢?

TodoList 类中的 Todos 变量:
Todos 是复数,说明其类型可能是数组、List 或者其他的集合。
Todos 首字母大写,说明访问权限是 public 类型的。
Todos 名字本身是一个名词,解释成中文则是:要做的事(待办事项),本身准确地传达了变量的意思。
Todo 类
Id,和 Todos 一样,传达了访问权限,和意思(标识),但是没有传达其类型。不过,不管是 int 还是 string 都无所谓。
Finished,也是一样的,public 权限、意思(完成了)。同样也没有传达其类型,不过这里可以这样理解,Finish 是动词,加上 ed 则是过去式,有时态说明有状态,这个状态只有两个,完成和未完成,所以是 bool 类型,这是笔者的一个习惯,当然也可以命名为 IsFinish,等等。
Content,中文意思是内容,也就是文本内容,一般为 string 类型,因为首字母大写,所以也是 public 权限。
简单几行代码,就可以传达这么多信息,所以 命名是一门艺术。

小结
在对一个变量进行命名的时候,无非要思考以下三点:

描述
权限
类型
权限和类型的表达很容易,因为关于这方面的方法论(套路)是固定的,可以很容易掌握的。

比较考验功底的是变量的描述,是需要长期进行训练的。

描述、权限、类型
接下来以这三点为主,分别进行方法论的介绍。

先从最简单的来,最简单的则是 权限 的表达

权限
权限指的是访问权限,在 C# 中有 public、private、protected、internal 类型。

这里在进行变量命名时分为两种。

可外部访问的 public 和 internal。
和不可被外部访问的 private 和 protected。
权限的表达,笔者自己的习惯是,可被外部访问的变量采用首字母大写。

比如:

public string Name;
internal static int ReferenceCount;
而不可被外部访问的变量采用 m 前缀。

比如:

private string mShowedText;
protected int mMgrId;
这是笔者长期的一个习惯,也是笔者自己维护的 QFramework 的命名规范。

所以关于权限的表达非常简单,依靠代码规范就能搞定了,规范怎么定就怎么用。

这一点是最最最容易达到的。

如果各位还没有开始在意命名这件事情,从权限开始上手是最容易的。

类型
变量是有类型的,最好呢是把类型能够表达出来。

类型的表达,当然这也可以依照某些代码规范来解决的。

比如匈牙利式的代码规范:

private int m_nAge; // n 代表数量
private string m_strName // str 代表 string
不过这种规范需要适应一段时间,这里笔者不太推荐新手用这种规范解决类型表达问题。

而是采用一种比较简洁、优雅的方式,来表达变量的类型。

比如:

public int Age;
Age 年龄,很容易想到是 int 类型。

public string Name;
Name 名字很容易想到是 string 类型。

public int PetCount;
public int PetNumber;
宠物数量,很容易想到是 int 类型。

public bool Completed;
Completed 完成了,是 bool 类型。

而这部分的详细内容会在接下来的一个小节中详细介绍。

描述
关于变量的描述的内容就比较多了,但是原则很简单,就两个字:准确。

为变量命名时最重要的考虑事项是,该名字要完全、准确地描述出该变量所代表的事物。——《代码大全》

如何达到准确呢?这部分也会在接下来的一个小节中介绍。

在本小节,先给大家对变量所用的词类型进行简单的分类:

事物
string
Name
NickName
int
Age
XXXCount
Times

状态
过去式
Finished
进行时
Waiting
一些不推荐使用的(IsXXX):
IsFinished
IsFinish
IsWaiting
形容词
active
其他
C# 中特有的 委托、事件 等。
OnXXXFinished
OnBeforeDestroy
OnLoadDone
OnLoadStart
所以在之后详细讲述变量的描述表达部分会根据这三点来进行介绍。

小结
读者读到这里,权限的表达是最容易做到的,如果没有意识到的童鞋们,可以在工作中开始权限的表达训练了。

权限的表达比较适合作为变量名训练的的第一步。

关于权限部分的内容就到此完结了,下文中不再赘述。

而剩下的类型和描述用两个大章节进行详细介绍。

我们先搞定相对较容易的类型的表达,这样好让大家掌握并快速在工作中实践。

类型的表达
关于集合(List、Array、Dictionary 等等)
List、Array 可以使用名词的复数来搞定。

比如:

var todos = new List();
var todos = new Todo[]{};
也可以将集合类型作为后缀表达

var todoList = new List();
var todoArray = new List();
Dictionary

因为是 key-value 类型的集合,可以使用 xxx4yyy方式命名(4 = for),这是笔者个人习惯,不强制。

var todo4Id = new Dictionary();
也可以使用类型作为后缀。

var todoDict = new Dictionary();
但是 key-value 类型使用 类型作为后缀表达效果较差,所以推荐 xxx4yyy 方式。

其他的集合类型,比如 Queue、Stack 等,也同样可以采用类型后缀的方式。

var panelStack = new Stack();
var msgQueue = new Queue();
Stack 和 Queue 是技术概念,所以一般会在框架/插件/工具层使用,在业务层使用得较少。

集合类型部分介绍到这里。

数值/数据类型、string/char 等 (事物)
数值类型(int/flout/double):
int 类型常见的后缀词(限定词):

Number

var todoNumber = todos.Length;
Index

var todoIndex = todos.IndexOf(todo);
Count

var todoCount = todos.Count;
int 类型常见的前缀词:

num

var numTodos = todos.Length; // number of todos 缩写,不太常用。
float/double 类型常见的后缀词
Average、Sum 等。

var ageAverage = ageSum / peopleCount;
这种类型的后缀词和前缀词在计算时经常会用到。

这里叫做计算限定词。
下面列出常用的计算限定词:

Count、Number、Num、Index、Total、Sum、Average、Max、Min、Record 等。
《代码大全》建议,除了 Num 之外其他的都建议放到后缀

还有一些数值类型的名字本身就表达了其类型。

age(int)、times(int) 等。
数据类型(string/char):
数据类型没什么好说的,只能尽量选取名字本身就表达其类型的这种名字,而这部分的内容算是描述的表达部分,这里先列出一部分:

username(string)、password(string)、name(string)、content(string)、title(string)、description(string)、id(int/string) 等。
bool、枚举(状态)
bool 类型:
使用动词 + 时态。
done
finished
completed
updating
enabled
使用 Is + 名词。
isEnemy
形容词
active
给 bool 类型取名的原则很简单,只要表示其状态只有两种就好。
比如 GameObject 要么为 激活状态 (active 为 true) ,要么为 未激活状态 (active 为 false)。符合这样的就是一个很好的 bool 变量名,不可能有第三个状态的。

再比如,一个任务要么完成(finished 为 true),要么为未完成(finished 为 false)。

枚举
枚举部分要分两个部分讲,一个是定义部分,一个是变量部分。
枚举的定义:

// 事件
public enum UIMainPanelEvent
{

// 事件监听
OnModelDataChanged,

// 指令 (动宾短语、动词)
UpdateView

}

// 状态 (与 bool 类型一样)
public enum ResLoadState
{

LoadBegan,
Loading,
LoadEnded,

}

// 结果 (名词、形容词)
public enum ResLoadResult
{

Success,
Fail,

}
定义部分和 bool 类型很像,比如 ModelDataChanged 就是 动词 + 时态的方式。

Unity 特有的 GameObject、Transform、Button、Image 等
GameObject heroObj;
GameObject heroGameObj;
Transform heroTrans;
Button btnEnterMainPanel;
Image logoImage;
以上为常见的前缀、和后缀。

关于类型的表达介绍就到这里。

小结
到这里我们对类型的表达进行了详尽的介绍。
笔者关于类型表达的方法论也都全部介绍完了,大家可以笔者的方法论为准进行练习,在此基础上进行不断思考改进称为自己的方法论。

思考什么呢?
思考如何让别人(或自己)在别的文件中使用变量就能猜到其类型呢?
所以笔者介绍的方法论不是重点也不是权威,重点是不断进行思考。

描述的表达
终于到了重头戏了。
描述的表达是能够考验一个开发者功底的工作。

对于 Model 类的变量命名。

要想有一个好的描述,必须非常了解业务的。
因为只有非常了解业务了,才能找到非常准确的描述。
就像本 Chat 的开头的入门那样:

业务最起码应该是梳理过一次的,梳理成自己能理解。
梳理过一次之后要再进行一次结构化的梳理,这样比较好转化为代码。
结构化梳理之后才能定义 Model 类和其变量。
以上对各位的要求会比较高,所以笔者这里建议,大家熟练掌握了了权限和类型的表达后在进行描述的练习。

而在这之前,本 Chat 也只是介绍了 Model 的变量命名。
这是因为 Model 的变量定义是相对容易的。但是我们的工作不只有定义 Model,还有好多其他的类需要我们定义,而定义类多少要定义一些变量。而本 Chat 不能覆盖所有的变量命名场景,所以会给出一些准则和练习步骤来给大家参考。

练习步骤一: 代码部分全部为英文。
在 Unity 中少数的需要显示在编辑器上提供参数调整的变量可以用一些中文汉字。而剩余的最好是全部使用英文。
这里最好是在编码时随手备着一个查词软件,可以通过键盘快捷键快速查询的。要养成这个习惯。到最好发现,在某一个领域或某种业务常用的词汇就那些,自己都记住了,很少会再编码时使用查词软件。

练习步骤二: 业务命名而不是技术命名
这个标题是笔者自己理解的,《代码大全》的描述是变量名应该描述的是 what 而不是 how。也就是变量是什么而不是怎么做。
因为业务概念是现实的模拟,而技术概念只是手段。所以笔者理解为为了业务命名而不是为技术命名。

要理解此准则非常简单。摘抄《代码大全》的一段话给大家理解:

一个好记的名字反映的通常都是问题,而不是解决方案。一个好名字通常表达的是“什么”(what),而不是“如何”(how)。一般而言,如果一个名字反映了计算的某些方面而不是问题本身,那么它反映的就是“how”而非“what”了。请避免选取这样的名字,而应该在名字中反映出问题本身。

一条员工数据记录可以称作 inputRecord 或者 employeeData。inputRecord 是一个反映输入、记录这些计算概念的计算机术语。employeeData 则指的是问题领域,与计算世界无关。与此类似,对一个用于表示打印状态的位域来说,bitFlag 就要比 printerReady 更具计算机特征。在财务软件里,calculateValue 的计算痕迹(how) 也要比 sum (what) 明显。

书中原文解释的很清楚了,不再多说了。

练习步骤三:分清楚何时用技术命名
这里要说一点注意的,要分清楚在哪个层。举一个笔者框架中的 SerializeHelper (序列化器),序列化是技术概念,是“怎么做?” (how),但是它可以做游戏数据的存储等操作。那么它为什么不叫做 DataSaver/DataLoader 这些名字呢?

这是因为 SerializeHelper 这个类不在业务层,而是在框架层。框架本身提供的更多的是工具。

小结
练习步骤给出了 1、2、3,很容易上手,命名这件事本身比较容易掌握,难得是初学者非常不在意。老手呢一般趟坑躺多了自然就会意识到。而初学者再去趟一下这些坑有点浪费时间,不如一开始就意识到命名这件事的重要性。

到此呢,权限、类型、描述的练习步骤和原则(准则)都给了。接下来简单聊聊,为什么要命名和如何更容易地落实命名这件事到工作中呢?

为什么要命名?
代码的本质是信息,其承载着信息,这个信息可以被编译器理解,也要被人理解。

首先你,代码要被编译器理解,这是最基本的要求,也代表着开发者能和计算机沟通,让计算机帮忙处理任务。

其次呢,是要被人理解。

这些人可能是:

自己(日常)
与自己朝夕相处时间最长的就是这些代码了,如果代码非常容易读懂并且整洁,每天的工作状态都会不一样。
在 debug 时候,还是要去读代码的,好的代码是更容易被阅读的,容易被阅读 debug 所花费的时间就会减少。
增加功能,也还是一样需要阅读代码的,以上同理。
使自己对项目的理解更深刻、清晰。

同事(协作)
同样代码被容易阅读,同事的效率也有所提升,也会得到同事的认可,
leader(晋升)
很多团队有代码 review 的文化,好的代码更容易获得上级和同事的认可。
得到同事和上级的认可,晋升就是很自然的事情了。
来接手项目的人(离职)
离职的时间也会被节省,不会被拖着问这是什么那是什么。
所有开发者(开源)
节省非常多人的时间,时间就是生命。
读者(教学,正在读本 chat 的各位则是这个范围的)
最终受益最多的还是自己,而投入的只不过每个变量多花费了几秒的思考时间而已。

总之协作这个词有一个协字,可以理解成妥协的协,也可以理解成协助的协。

给变量合适的命名既是一种妥协也是一种协助。

这就是为什么笔者单开一个 chat 来写一个大家认为如此简单的事情。

如何落地变量的命名
单写这一小节是希望大家不是只读一读这篇 chat 就完事了,而是要把变量的命名这件事情落实到自己产出的代码上去。

在工作中养成一个习惯的阻碍有很多。
最常见的原因就是项目时间紧。

这个问题很好解决,只要训练的时机根据实际情况进行调整就好了。

对于初学者或者项目非常紧急的开发者,在第一遍写逻辑的时候,变量可以先随便命名(按照自己的习惯),但是只要当前的测试点验证通过或者功能点完成,就应该回过头把变量的名字好好想下,进行重新命名。一般 IDE 都带重构功能,只要改一个地方,其他代码部分会全部跟着更改。

这样做的目的是为了防止同一时间做两件事情。

逻辑编写
变量命名
对于命名新手来说,同一时间做两件事情会很吃力。
本身逻辑编写就很吃力了,再加上需要思考的变量命名,会更加吃力。
所以对于命名新手要求同一时间只思考一件事情。

对于时间非常紧急的开发者,如果进行命名的思考会影响项目的进度,那还是等项目不急的时候再落实就好了。

只要能做到,在进行逻辑编写时,只考虑如何完成或者如何实现就好了。
在变量命名时,只专注于如何取个合适的名字,只考虑变量的描述、类型、权限就好。
如下:

变量的命名是否准确描述?
变量的命名是否表达了类型?
变量的命名是否表示了权限?
这样坚持一段时间后,就能做到同一时间就可以做两件事情。

初学者们只要记住一点就够了:

合适的命名可以不在创建变量的时候完成。
但是最终目标还是将进行合适的命名这件事情养成习惯,在创建变量的同时就已经为变量取了一个非常合适的名字。

最后,非常感谢 QFramework 的 边上海 边前辈对此专栏的勘误和提供的一些非常有价值的建议。

原文地址https://www.cnblogs.com/liangxiegame/p/12591418.html

相关文章
|
3月前
|
图形学 C#
超实用!深度解析Unity引擎,手把手教你从零开始构建精美的2D平面冒险游戏,涵盖资源导入、角色控制与动画、碰撞检测等核心技巧,打造沉浸式游戏体验完全指南
【8月更文挑战第31天】本文是 Unity 2D 游戏开发的全面指南,手把手教你从零开始构建精美的平面冒险游戏。首先,通过 Unity Hub 创建 2D 项目并导入游戏资源。接着,编写 `PlayerController` 脚本来实现角色移动,并添加动画以增强视觉效果。最后,通过 Collider 2D 组件实现碰撞检测等游戏机制。每一步均展示 Unity 在 2D 游戏开发中的强大功能。
176 6
|
2月前
|
测试技术 C# 图形学
掌握Unity调试与测试的终极指南:从内置调试工具到自动化测试框架,全方位保障游戏品质不踩坑,打造流畅游戏体验的必备技能大揭秘!
【9月更文挑战第1天】在开发游戏时,Unity 引擎让创意变为现实。但软件开发中难免遇到 Bug,若不解决,将严重影响用户体验。调试与测试成为确保游戏质量的最后一道防线。本文介绍如何利用 Unity 的调试工具高效排查问题,并通过 Profiler 分析性能瓶颈。此外,Unity Test Framework 支持自动化测试,提高开发效率。结合单元测试与集成测试,确保游戏逻辑正确无误。对于在线游戏,还需进行压力测试以验证服务器稳定性。总之,调试与测试贯穿游戏开发全流程,确保最终作品既好玩又稳定。
105 4
|
3月前
|
图形学 缓存 算法
掌握这五大绝招,让您的Unity游戏瞬间加载完毕,从此告别漫长等待,大幅提升玩家首次体验的满意度与留存率!
【8月更文挑战第31天】游戏的加载时间是影响玩家初次体验的关键因素,特别是在移动设备上。本文介绍了几种常见的Unity游戏加载优化方法,包括资源的预加载与异步加载、使用AssetBundles管理动态资源、纹理和模型优化、合理利用缓存系统以及脚本优化。通过具体示例代码展示了如何实现异步加载场景,并提出了针对不同资源的优化策略。综合运用这些技术可以显著缩短加载时间,提升玩家满意度。
154 5
|
2月前
|
前端开发 图形学 开发者
【独家揭秘】那些让你的游戏瞬间鲜活起来的Unity UI动画技巧:从零开始打造动态按钮,提升玩家交互体验的绝招大公开!
【9月更文挑战第1天】在游戏开发领域,Unity 是最受欢迎的游戏引擎之一,其强大的跨平台发布能力和丰富的功能集让开发者能够迅速打造出高质量的游戏。优秀的 UI 设计对于游戏至关重要,尤其是在手游市场,出色的 UI 能给玩家留下深刻的第一印象。Unity 的 UGUI 系统提供了一整套解决方案,包括 Canvas、Image 和 Button 等组件,支持添加各种动画效果。
136 3
|
2月前
|
设计模式 存储 人工智能
深度解析Unity游戏开发:从零构建可扩展与可维护的游戏架构,让你的游戏项目在模块化设计、脚本对象运用及状态模式处理中焕发新生,实现高效迭代与团队协作的完美平衡之路
【9月更文挑战第1天】游戏开发中的架构设计是项目成功的关键。良好的架构能提升开发效率并确保项目的长期可维护性和可扩展性。在使用Unity引擎时,合理的架构尤为重要。本文探讨了如何在Unity中实现可扩展且易维护的游戏架构,包括模块化设计、使用脚本对象管理数据、应用设计模式(如状态模式)及采用MVC/MVVM架构模式。通过这些方法,可以显著提高开发效率和游戏质量。例如,模块化设计将游戏拆分为独立模块。
185 3
|
3月前
|
图形学 开发者 存储
超越基础教程:深度拆解Unity地形编辑器的每一个隐藏角落,让你的游戏世界既浩瀚无垠又细节满满——从新手到高手的全面技巧升级秘籍
【8月更文挑战第31天】Unity地形编辑器是游戏开发中的重要工具,可快速创建复杂多变的游戏环境。本文通过比较不同地形编辑技术,详细介绍如何利用其功能构建广阔且精细的游戏世界,并提供具体示例代码,展示从基础地形绘制到植被与纹理添加的全过程。通过学习这些技巧,开发者能显著提升游戏画面质量和玩家体验。
152 3
|
2月前
|
图形学 C++ C#
Unity插件开发全攻略:从零起步教你用C++扩展游戏功能,解锁Unity新玩法的详细步骤与实战技巧大公开
【8月更文挑战第31天】Unity 是一款功能强大的游戏开发引擎,支持多平台发布并拥有丰富的插件生态系统。本文介绍 Unity 插件开发基础,帮助读者从零开始编写自定义插件以扩展其功能。插件通常用 C++ 编写,通过 Mono C# 运行时调用,需在不同平台上编译。文中详细讲解了开发环境搭建、简单插件编写及在 Unity 中调用的方法,包括创建 C# 封装脚本和处理跨平台问题,助力开发者提升游戏开发效率。
214 0
|
2月前
|
vr&ar 图形学 API
Unity与VR控制器交互全解:从基础配置到力反馈应用,多角度提升虚拟现实游戏的真实感与沉浸体验大揭秘
【8月更文挑战第31天】虚拟现实(VR)技术迅猛发展,Unity作为主流游戏开发引擎,支持多种VR硬件并提供丰富的API,尤其在VR控制器交互设计上具备高度灵活性。本文详细介绍了如何在Unity中配置VR支持、设置控制器、实现按钮交互及力反馈,结合碰撞检测和物理引擎提升真实感,助力开发者创造沉浸式体验。
155 0
|
2月前
|
图形学 开发者
【独家揭秘】Unity游戏开发秘籍:从基础到进阶,掌握材质与纹理的艺术,打造超现实游戏视效的全过程剖析——案例教你如何让每一面墙都会“说话”
【8月更文挑战第31天】Unity 是全球领先的跨平台游戏开发引擎,以其高效性能和丰富的工具集著称,尤其在提升游戏视觉效果方面表现突出。本文通过具体案例分析,介绍如何利用 Unity 中的材质与纹理技术打造逼真且具艺术感的游戏世界。材质定义物体表面属性,如颜色、光滑度等;纹理则用于模拟真实细节。结合使用两者可显著增强场景真实感。以 FPS 游戏为例,通过调整材质参数和编写脚本动态改变属性,可实现自然视觉效果。此外,Unity 还提供了多种高级技术和优化方法供开发者探索。
54 0
|
3月前
|
开发者 图形学 API
从零起步,深度揭秘:运用Unity引擎及网络编程技术,一步步搭建属于你的实时多人在线对战游戏平台——详尽指南与实战代码解析,带你轻松掌握网络化游戏开发的核心要领与最佳实践路径
【8月更文挑战第31天】构建实时多人对战平台是技术与创意的结合。本文使用成熟的Unity游戏开发引擎,从零开始指导读者搭建简单的实时对战平台。内容涵盖网络架构设计、Unity网络API应用及客户端与服务器通信。首先,创建新项目并选择适合多人游戏的模板,使用推荐的网络传输层。接着,定义基本玩法,如2D多人射击游戏,创建角色预制件并添加Rigidbody2D组件。然后,引入网络身份组件以同步对象状态。通过示例代码展示玩家控制逻辑,包括移动和发射子弹功能。最后,设置服务器端逻辑,处理客户端连接和断开。本文帮助读者掌握构建Unity多人对战平台的核心知识,为进一步开发打下基础。
129 0
下一篇
无影云桌面