o111 发表于 2024-7-15 18:42

Unity游戏开发读书笔记(一)软件架构

1.1 软件架构的意义

在一个软件系统中,架构的重要性不言而喻。从开发到运行,我们需要从分歧的选项中选择合适的架构和技术方案。比如,我们应该开发本身的前端衬着引擎还是使用商业引擎?我们应该使用 Unity3D、Unreal 还是其他引擎?我们应该使用 UGUI 还是 NGUI?UI中的事件系统应该如何统一措置?我们应该为 AI 行为算法选择行为树、状态机还是选择事件的决策树还是分层任务网络?数据应该如何获取和存储?场景应该如何分割?资源应该分隔加载吗?我们应该使用长连接还是短连接?我们应该选择 TCP 还是 UDP?我们应该在处事器端使用 C++、Java 还是 Python?是完全使用关系型数据库还是插手缓存机制?我们应该使用 Protocol Buff、JSON、XML格式的序列化方案来传输网络数据吗?
这些项目中的每个子系统都需要有本身的标的目的。将各个子系统的决策标的目的组合起来,加上它们的关联调用,就构成了一个完整的体系布局,此中的各个系统、模块、组件都是软件系统体系布局的组成部门。
一个优秀的架构师不仅需要仔细考虑各个子系统的决策标的目的,还需要结合其他系统和整体系统需求进行设计。
在架构设计中,为了更好地组织、思考、描述和表达,我们应该使用架构图。架构师将架构中的抽象系统、模块和组件绘制在图上,用圆圈、正方形和文字来暗示,以便本身和他人理解架构的意图和布局,以及架构的简要设计子系统。
一个完整的架构图凡是带有子系统甚至子模块架构图的一些细节。UML对象关系图是一种描述数据类之间关系的体系布局图,可以用文字和连接图清楚地描述系统中的对象。部署图也是一种架构图,清楚地描述了需要多少台处事器,它们扮演什么角色,它们之间的关系如何,而挨次图则清楚地描述了系统法式调用的挨次和流程。
软件架构可以比作现实生活中的书架。 书架设计有许多大大小小的网格,可以容纳分歧类型的节目,就像书架可以容纳分歧类型的册本一样。 搁板可以有分歧的尺寸,具体取决于客户的需求,较大的搁板设计用于容纳更多的法式,而较小的搁板则用于便利和快速。
书架的好坏可以按照其承载能力、伸缩性、易用性和伸缩性来评价。 承载能力是指这个架构能承载多少个逻辑系统,扩展到100万行代码时,是否还能有序、规范地运行。 例如,对于处事器来说,承载能力可能是指该架构可以措置多少人同时访谒该网站。 可扩展性是指货架是否可以适应分歧类型的需求,比如在不影响或减少其他子系统运行的情况下添加新的子系统。 易用性是指这个架子是否对用户友好,法式员是否可以很便利地与它对接子系统,从而提高架构的效率。 最后,可扩展性指的是书架是否可以按照用户的需要缩小到更小的尺寸,就像一个可折叠的书架。
这些因素中的每一个对于评估架构的质量都是至关重要的。 承重能力当然重要,但并不是决定书架质量的独一因素。 需要对这些因素进行综合评价,才能判断架构的好坏。
1.2 架构的设计

软件开发和架构设计最需要的能力之一就是抽象能力,抽象能力有助于凭空缔造一个方针实体,为方针勾画出一个概略的轮廓,让路上有一个看得见的尺度和方针。
首先介绍的思维方式是分层思维,这是措置和打点复杂性的一种精神刀兵。在构建一个复杂的系统时,整个系统被划分为若干层,每一层都专注于解决某一范围的问题,并向上提供处事。分层思维有助于将复杂系统的架构层次抽象出来,从而清晰地描述需要解决多少层事务,以及解决优先级的层级。
第二种介绍的思维方式是分而治之思维,这也是措置和打点复杂性的通用方式。对于一次无法解决的大问题,将问题分化为若干个子问题,如果子问题无法解决,则进一步分化为子问题,直到可以直接解决为止。然后,将子问题的解组合成原问题的解。
介绍的第三种思维方式是演化思维,架构既是设计出来的,同时也是演化出来的。对于互联网系统,基本上可以说是三分设计,七分演化,既在设计中演化,又在演化 中设计,是一个不竭迭代的过程。从单块架构开始,随着架构师对业务域理解的不竭深入,也随着业务和团队规模的不竭扩大,渐进式地把单块架构拆分成微处事架构的思 路,就是演化式架构的思维。
受职业习惯影响,优秀架构师看到的世界是模块化组合模式。模块化思维是在大脑中形成抽象的概念,以模块的形式进行开发,设计子模块之间的通信方式,依次实现子模块,最后将子模块组合起来形成最终的系统。
总体而言,软件架构设计需要分歧的思维方式,这些思维方式有助于打点复杂性并使抽象概念更加具体。
1.3 如何构建Unity3D项目

前面我们对软件架构进行了解释,而且对软件架构抽象的思维方式 进行了详细介绍,包罗分层、分治、演化。本书将具体介绍架构中的误 区,以及如何做前端架构,而且了解如何构建Unity3D项目。
1.前端与后端架构之间的共性
前后端架构的方针都是高性能、高可用、可扩展、安全、可容错。 对于前端来说,除了这些方针特性外,还需要插手更多的用户体验,包 括视觉效果和操作灵敏度。 作为前端工程师,用户体验是斗劲重要的,这种体验涉及很多方 面,包罗性能、视觉效果,以及操作上的人性化等。例如,如何让游戏 加载速度更流畅、如何制作更灿艳的特效、如何减少电量的消耗、如何 最快地响应用户操作等。 前端技术与后端技术都是在同一个系统层面上成立起来的,都是建 立在Linux、Windows、Android、iOS操作系统之上的,两者最后都需要 开发者了解操作系统的接口以及底层运作道理。它们的区别在于,后端 在操作系统上构建了一套处事端框架,而前端在操作系统上构建了一个 衬着引擎,它们需要在此之上做业务架构。我们本身构建或选择某个商 业衬着引擎后,再在衬着引擎之上成立游戏应用的业务架构。
因此,我们其实有两套架构要学习,一套是衬着引擎架构,一套是游戏业务架构。 对衬着引擎架构的探讨偏离了本书的范围,这里不做详细阐述。游 戏业务架构中有很多需要我们搭建的框架,可以以模块形式来定名它 们,包罗网络框架、UI框架、数据框架、核心战斗框架、AI框架等,后面将进行讨论。
2.培养架构设计思维
良好的架构设计思维的培养,离不开工作中大量高质量项目的实战锻炼,以及平时的学习、思考和总结。 基本的架构设计思维在大学计算机课程(比如数据布局和算法)中 可以找到,大学里以学习理论常识为主。
随着经验的堆集,我们能够解决的问题的复杂性和规模逐渐变 大,但所用的方式依然是抽象、分层、分治和演化。 架构设计并不是静态的,而是动态的。只有不竭应对环境变化的系统,才是有生命力的系统。所以,即使你掌握了抽象、分层和分治这三 种基本思维,仍然需要演化式思维,在设计的同时,借助反馈和进化的力量敦促架构的持续演进。
架构师在存眷技术、开发应用的同时,需要按期梳理本身的架构设计思维,堆集的时间长了,对待世界事物的方式会发生底子性的变化, 你会发现我们生活的世界,其实也是在抽象、分层、分治和演化的基础 上构建起来的。架构设计思维的形成会对你的系统架构设计能力发生重大影响。可以说,对抽象、分层、分治和演化掌握的深度和灵活应用的程度,直接决定架构师解决问题域的复杂性和规模大小,是区分普通应用型架构师和平台型/系统型架构师的一个分水岭。
3.试着构建Unity3D项目
把整个项目分成五大层级,即网络层、数据打点层、资源打点层、 核心逻辑框架层、UI框架层。 这样一分就清晰地知道了我们需要做哪几大类的东西。只是这样拆分太笼统,出格是核心逻辑框架层,完全是概括性的层级,无法表达具 体的系统。所以我们要再次拆分层级,把太过于笼统的层级进行分层。 颠末分层后再采用分治的方式,把核心逻辑框架层拆成为东西编纂器、角色行为框架、AI框架、地图场景与寻路框架、着色器与特效、设备平台等。这些子层都在核心逻辑框架层中,它们有本身的框架,也可以互相调用,它们一起构成核心逻辑部门,也就是核心玩法或核心战斗 的主要部门。
分层后再分治
我们再将资源打点层和数据打点层进行拆分,分为AssetBundle资源打点和Prefab资源打点,以及内存数据打点和外部数据打点,这样更清 晰地分工了各层的本能机能。其实还有很多其他的层级这里没有提到,包罗 常用库、东西库、动画控制等,这里暂纷歧一提出。 在游戏项目中,最常用的是数据表、网络层、UI层、常用库这几个模块。我们可以使用这种层级的方式来试着搭建一个完整的项目,只是 做抽象的编写,就可以清晰地知道这个项目需要哪些模块和层级。 比如,如果项目是单机的策略类游戏,可能就没有很多角色上的东 西,而多了很多2D动画行为控制上的需求。这时在进行层级划分时, 就可以把注意力重点放在2D动画行为控制、UI框架、数据打点、资源 打点及AI上。 如果项目是以3D人物角色为主的网络游戏,则应有地形地图、角色行为控制等内容,此外,还需要一套角色技能、特效、动画编纂东西 等。网络游戏项目前期我们会对网络这块内容进行决策,确定是TCP、Socket、UDP还是Web形式的HTTP。3D MMRPG的难度主要集中在了 解角色技能动画、AI、地图、物理模拟上。我们可以把重点提取出来, 让擅长的同事专门做这块内容的深度挖掘,把最难把控的放在最优先的 位置去做,再对这些层级进行细致化构建。 对模块进行细致化构建时,我们可以使用分治法去构建。如果某个要解决的问题已经确定,且这个问题的规模太大,无法直接下手解决, 那么可以使用分治法,把一个问题分成几个小问题来措置,把小问题再 划分成更小的问题,直到能直接解决为止,再依次对它们进行措置。



客户端框架架构设计



网络层设计

我们把网络层拆分成HTTP、TCP-Socket、UDP这三种 类型的形式,再对每个类型的具体接口进行拆分,对于拆分出来的每个 接口,如果还不能直接使用,则再进行细致的拆分,直到拆分到可以具 体实施为止。
我们以接口的形式进行拆分,先将接口拆分 成连接、断开连接、发送数据、收到数据,以及(断开、连接、终结) 网络事件,然后再对每个接口进行拆分,把接口需要措置的问题拆分出 来各个击破。
除了我们列举的网络层外,其他层级部门的框架也可以用同样的方式进行分化,即用分而治之的方式逐个击破每个模块。下面描述了一个简单的3D MMORPG的一些模块的拆分原则。

[*]数据表:EXL导为二进制文件、JSON或其他格式,读取接口和解析接口的定义。
[*] UI层:确定是使用NGUI还是UGUI还是FairyGUI,并针对界面基类、界面管 理、输入事件封装进行选择,且自定义通用组件基类和各类通用组件。
[*] 外部资源打点:确定是否使用AssetBundle,是否对AssetBundle资 源进行分类,是否依赖AssetBundle资源间的关系,是否加载与释放 AssetBundle的打点,是否加密AssetBundle。
[*]AI层:确定是使用状态机还是行为树或者其他,以及状态机或行为树接口的实现、AI可视化东西、AI扩展接口。
[*]地形地图:包罗地图是2D的还是3D的,场景编纂器的布局是否需 要网络合并,场景内的大小物件区别对待,大地形在游戏里如何显示, 是否要划分区块。
[*]寻路与网格:确定是使用A星算法还是跳点算法或者其他算法;是使用网格栅格还是三角网格;是使用长距离寻路的解决方案还是地图数 据打点。
[*]常用库:包罗时间函数、数学函数、数字变量加密封装、坐标转换函数、Debug调试东西、各大逻辑系统通用东西等。
[*]角色行为控制:包罗人物移动措置方案、摄像机的碰撞检测、动画特效编纂器、技能编纂器、行为流的成立。
[*]2D动画控制:包罗动画组件封装、2D动画的制作流程、2D图合并 为图集。
实际工作中,我们对层级和模块逐个攻破的同时,也进入了架构演化模式。在一开始构建的架构中,某部门的设计可能并不十分合适,在 后面的工作中我们需要对其逐步修复、完善甚至替换,这些都是演化的重要法式。 在不竭完善架构的过程中,原本简单抽象的架构开始复杂化。每个模块都在有条不紊地演进,也会不竭冒出各种各样不适应或者不符合实 际需求的问题,我们需要及时跟进演化内容,包罗剔除、重构、改善、 修补前面由于各种原因而导致的错误。 最后应该注意架构设计的文档要及时跟进完善,在抽象的过程中,我们需要整理和记录整个过程,以便在此后完善架构时有途径获得前面 在做决策时所考虑的各方面问题。
页: [1]
查看完整版本: Unity游戏开发读书笔记(一)软件架构