《Unity3D高级编程之进阶主程》第二章,架构(三) - 架构的误区,如何做前端架构,以及如何架构Unity3D项目

前文我们对软件系统架构进行一个彻头彻尾的解释。并且对软件系统架构抽象的思维方式进行了一番详细介绍,包括了分层,分治,演化。这篇我们将来具体介绍下,架构中的误区,以及如何做前端架构,并且了解下如何架构Unity3D项目。

===

前端与后端架构之间的共性

前后端架构的目标都是,高性能、高可用、可扩展、安全、可容错。对于前端来说除了这些目标特性外,我们还需要加入更多的用户体验,包括视觉效果和操作灵敏度。

作为前端工程师,用户体验是比较重要的,但这种体验涉及到很多方面,包括性能优化,视觉效果,以及操作上的人性化等,例如如何让游戏加载更快,如何制作更绚丽的特效,如何减少Drawcall,如何减少CPU的负载,如何最快的响应用户操作等。

前端技术与后端技术,都是在同一个系统层面上建立起来的,都是建立在Linux,Windows,Android,IOS,操作系统之上的,两者最后要需要了解操作系统的接口以及底层运作原理。区别在于后端在操作系统上构建了一套服务端框架,而前端在操作系统之上构建了一个渲染引擎,两者都需要在这之上构建业务架构。当我们自己构建了或选择使用商业渲染引擎后,再在渲染引擎之上建立游戏应用的业务架构,因此我们其实有两套架构要学习,一套是渲染引擎架构,一套是游戏业务架构。

对渲染引擎架构的探讨偏离了书本的初衷,留给作者在其他文章中再来详细讲解。在游戏架构中有很多需要我们搭建的框架,我们可以以模块形式来命名它们,包括网络框架,UI框架,数据框架,核心战斗框架,AI框架等我们将在下面的文章中讨论。

培养架构设计思维

良好的架构设计思维的培养,离不开工作中大量高质量项目的实战锻炼,然后是平时的学习、思考和提炼总结。

基本的架构设计思维,其实在我们大学计算机课程(比如数据结构和算法)中可以找到影子,大学里以学习理论知识为主,需要在具体的工作中实践他们。其实大学教育其实非常重要,基本的架构设计思维在那个时候就已经埋下种子,后面工程实践中会进一步消化和应用,随着经验的积累我们能够解决的问题的复杂性和规模逐渐变大,所用的方法就是抽象,包括分层、分治、演化。

架构设计不是静态的,而是动态的。只有能够不断应对环境变化的系统,才是有生命力的系统。所以即使你掌握了抽象、分层和分治这三种基本思维,仍然需要演化式思维,在设计的同时,借助反馈和进化的力量推动架构的持续演进。

架构师在关注技术,开发应用的同时,需要定期梳理自己的架构设计思维,积累时间长了,你看待世界事物的方式会发生根本性变化,你会发现我们生活其中的世界,其实也是在抽象、分层、分治和演化的基础上构建起来的。架构设计思维的形成,会对你的系统架构设计能力产生重大影响。可以说对抽象、分层、分治和演化掌握的深度和灵活应用的水平,直接决定架构师所能解决问题域的复杂性和规模大小,是区分普通应用型架构师和平台型/系统型架构师的一个分水岭。

试着架构Unity3D项目

我们可以用以上的方法来试着架构Unity3D项目,我们用分层的思维方式,先确定架构的层级,如下图。

Unity3D架构1

把整个项目分成五大层级,网络层,数据层,资源层,核心逻辑框架层,UI层。

这样一分清晰的知道了我们需要做哪几块大类的东西。但是这样拆分太笼统,特别是核心逻辑框架这块,完全是概括性的层级,无法表达具体的系统。所以我们再拆分层级。把太过于笼统的层级进行再分层。如下图:

Unity3D架构2

经过再分层后,把核心逻辑框架分成了,工具编辑器,角色行为框架,AI框架,地图场景与寻路框架,Shader与特效,设备原始接口。这些子层都是在核心逻辑层中,他们有自己的框架,也可以互相调用,构成了核心逻辑部分,也就是核心玩法或者说核心战斗的主要部分。

我们将资源管理层和数据管理层再进行了拆分,分成了Assetbundle资源管理和Prefab资源管理,以及内存数据管理和外部数据管理,这样更清晰的分工了各层的职能。其实还有很多其他的层级我们这里没有提到的,包括常用库,工具库,动画控制等,这里暂不一一提出来。

在游戏项目中最常用的是,数据表,网络层,UI层,常用库,这几个模块。我们可以用这个层级的方式来试着搭建一个完整的项目,只是做抽象上的编写,就可以清晰的知道,这个项目需要哪些模块和层级了。

比如如果项目单机的策略类游戏,可能就没有很多角色上的东西,而多了很多2D动画行为控制上的需求。这时我们就可以把层级划分下,把注意力重点放在,2D动画行为控制,UI框架,数据管理,资源管理,以及AI上。

如果我们项目是3D人物角色为主的网络游戏,就有地形地图,角色行为控制,还需要一套角色技能特效动画编辑器。这时我们就需要把网络层这块好好决策下该用哪种框架,TCP-Socket?UDP?还是web形式的HTTP?!3DMMRPG的难度主要集中在了角色技能动画、AI、地图、物理模拟上。我们可以重点划分出来,找人专门做这块,把最难把控的放在最优先的位置去做,而后再对这些层级进行细致化的构建。

对模块进行细致化构建时,我们可以用分治法方法去构建。如果某个要解决的内容已经确定了,而这个内容或问题的规模还是太大,无法直接的下手解决,那么我们用分治的方法,把一个问题分成几个小问题来做,把小问题再划分成更小的问题直到小到能直接解决,再依次对他们跟进处理。

这里我们拿网络层来说,进行分而治之,如下图:

Unity3D架构3

图中我们把网络层拆分成http,tcp-socket,udp这三种类型的形式,再对每个类型的具体接口进行了拆分,对于拆分出来的每个接口,如果还不能直接使用再进行细致的拆分,直到拆分到可以具体实施了为止。在上图中,我们以接口的形式进行拆分,先将接口拆分成,连接,断开连接,发送数据,收到数据,以及(断开、连接、终结)网络事件,然后再对每个接口进行拆分,把接口需要处理的问题拆分出来各个击破。

除了我们举例的网络层,其他层级部分的框架也可以用同样的方式进行类似的分解,用分而治之的方法逐个击破每个模块。这里我们描述了各个模块的拆分原则:

数据表 -- XLS导为二进制文件还是Json或其他格式,读取接口和解析接口的定义。

UI层 -- 使用NGUI还是UGUI,界面基类,界面管理,输入事件封装,自定义通用组件基类,自定义各类通用组件。

外部资源管理 -— 是否使用AssetBundle,AssetBundle资源分类,AssetBundle资源间的依赖关系,加载与释放AssetBundle的管理,AssetBundle加密。

AI层 -— 使用状态机还是行为树或者其他,状态机或行为树接口实现,AI可视化工具,AI扩展接口。

地形地图 -— 地图是2D还是3D,场景编辑器的结构,是否需要Mesh合并,场景内的大小物件区别对待,大地形在游戏里该怎么逐步显示,是否要划分区块。

寻路与网格 -— 使用A星还是跳点算法或者其他,使用网格栅格还是三角网格,长距离寻路的解决方案,地图数据管理。

常用库 -— 时间函数,数学函数,数字变量加密封装,坐标转换函数,Debug调试工具,各大逻辑系统通用工具等等。

角色行为控制 -— 人物移动处理方案,摄像机的碰撞检测,动画特效编辑器,技能编辑器,行为流的建立。

2D动画控制 -— 动画组件封装,2D动画的制作流程,2D图合并为图集。

实际工作中,我们对层级和模块逐个攻破的同时,也进入架构演化模式。一开始的做的架构中某个部位的并不适合,或需要改善,在后面的工作中,修复和完善架构是演化的重要步骤。

在不断编写完善架构的过程中原本抽象简单的架构,开始复杂化。虽然每个模块都在有条不紊的进行中,但也会不断冒出各种各样不适应或者不符合实际需求的问题出现,我们需要及时跟进演化内容。去除、重构或者改善,前面由于各种原因而导致的错误的理解。

最后架构设计的文档要及时跟进完善,在抽象的过程中,我们需要整理和记录整个过程,以便为今后在完善时能够一下子翻阅到并记起当时在架构时所考虑的各方面问题的原因。

· 书籍著作, Unity3D, 前端技术

感谢您的耐心阅读

Thanks for your reading

  • 版权申明

    本文为博主原创文章,未经允许不得转载:

    《Unity3D高级编程之进阶主程》第二章,架构(三) - 架构的误区,如何做前端架构,以及如何架构Unity3D项目

    Copyright attention

    Please don't reprint without authorize.

  • 微信公众号,文章同步推送,致力于分享一个资深程序员在北上广深拼搏中对世界的理解

    QQ交流群: 777859752 (高级程序书友会)