一个项目开始立项的时候,最常见的一个情况就是:几个人一个小团队,开始什么也不做,开始写代码,验证逻辑,然后 game 就开始写起来了。公司的一些的所谓的领导层一开始就把游戏定义为“我们要做的一个大作”,那么这个事情本身就是一个笑话。没有任何的规划和设计,我们就妄图就写出一个所谓的杰出的作品出来是不现实的。Unity 再好用,以这个心态去做游戏,一定会写不出来好的游戏来。——刘钢《Unity 项目架构和开发管理》
看到视频中的这段话,吓得笔者赶紧为跑酷项目做了些准备。比如最常见的表现和逻辑的分离。
表现逻辑分离我们大家都知道,做项目尽可能地要把表现和逻辑分离。同样的跑酷项目也是如此,而最常用最经典的方式就是使用 MVC。
经典的 MVC 架构模式MVC 是在软件开发时最常用的架构模式,我想大家都应该接触过,所以 MVC 的概念在这里笔者不会浪费口舌去赘述,不了解的同学可以参阅阮一峰前辈的《谈谈MVC模式》。
跑酷项目中的 MVC跑酷项目代码的架构使用的是很简单的 MVC。笔者当时是按照如下的方式去进行划分的:
View 层是各个 UI 的 Transform 本身。
Ctrl 层则是挂在各个 View GameObject 上的 MonoBehaviour。
Model 层则是若干个提供数据增删改查的并且可以全局访问的单例。
跑酷的 MVC 架构图如下所示:
从今天的来看,这种 MVC 设计是一种很粗糙的设计,尤其是其 Model 层,颗粒度太大,其实再可以分出个 DataAccess 层。不过粗糙的好处就是初学者能够驾驭,是有存在的意义的。
到这里,架构这个词终于出现了。MVC 是一种架构模式,对程序进行 MVC 的划分是在进行架构活动。除了 MVC 架构模式,还有几种其他的架构模式。
而对程序进行 MVC 的划分,实际上是对代码进行结构的设计,所以对程序进行结构的设计是在进行架构活动。
到这里,我们知道了架构是我们每天都在做的事情(划分 MVC 或者说将代码的表现与逻辑层分离)。而对代码进行结构的设是否和架构的“约定、规则、共识”有关系呢?答案是肯定的。我们接着往下进行探索。
文件结构很多时候我们说的一个所谓的好的架构,直接就等于你要有一个好的标准,指定一些好的规则。——刘钢《Unity 架构设计与开发管理》
Unity 好的规则 3:我们在起一些文件夹的名字的时候,尽量和我们的 GameObject 对应起来,如果我们的 GameObject 叫做 PoolManager,我下面所有的代码也都起一个同样的名字叫 PoolManager,那么这样在以后找对应的程序结构的时候,会比较好理解一些。——刘钢《Unity 架构设计与开发管理》
而跑酷项目最初的部分代码文件结构如下:
Scripts
App
Objects
Stages // 关卡单元
XXStage.cs
...
Enemy // 敌人
EnemyCtrl.cs
EnemyModel.cs
Player // 角色
PlayerCtrl.cs
PlayerModel.cs
...
Managers
EnemyManager.cs * StageManager.cs
...
对于 MVC 的文件结构的划分,笔者在进行跑酷项目之前的其他项目的时候也尝试了别的方案。当时觉得这种方式找起来最方便。
在项目结束之后不久看到了一篇吴秦前辈的一篇好文《Unity3D手游开发实践》:
一般客户端用得比较多的 MVC 框架,怎么划分目录?
先按业务功能划分,再按照 MVC 来划分。“蛋糕心语”就是使用的这种方式。
先按MVC划分,再按照业务功能划分。“D9”、“宝宝斗场”、“魔法花园”、“腾讯桌球”、“欢乐麻将”使用的这种方式。
根据使用习惯,可以自行选择。个人推荐“先按业务功能划分,再按照 MVC 来划分”,使得模块更聚焦(高内聚),第二种方式用多了发现随着项目的运营模块增多,没有第一种那么好维护。——吴秦《Unity3D手游开发实践》
而笔者所采用的方式就是“先按照业务功能划分,再按照 MVC 来划分”。在这里仅仅是个建议,并不是一定要使用的方式。
QFramework 的第一个工具“单例模板”在跑酷项目的 MVC 中,笔者把 Model 层设计成了单例。为什么使用单例呢?
抛开粗糙的设计不说,先让我们简单分析下跑酷项目的 Model 层的特点:
Model 层的数据在整个软件的生命周期里只有一份。
Model 层的数据要对任何 Ctrl 都提供增删改查。