十全干货:核心游戏系统架构设计
http://www.gameres.com/677342.html 文/AI分享站Finney 首先先来定义一下什么是我这里说的核心游戏系统,一般来说,游戏可以大致分为两个部分,一个部分是我这里指的核心游戏部分,比如FPS里的射击战斗部分,或者如LOL里的战斗对抗部分,又或者是体育类游戏里的比赛部分等等。 这些是游戏里的主要玩的点,核心游戏部分可以很重,占到玩家80%以上的游戏时间,也可以很轻,甚至没有,像现在很火的列王的纷争(COK),几乎就是没有什么核心游戏部分。另一部分就是外围的辅助系统,比如装备,任务,社交等等,这部分也有玩点和设计用意,这两个部分相辅相成组成了大部分游戏的主体框架。而今天要聊的就是第一部分的核心游戏系统。 从开始做游戏到现在,我大部分的工作是专注在引擎以及核心游戏系统部分,所以今天就想来聊聊如何来设计核心游戏系统。当然这个设计不一定适用于所有的游戏,仅仅是我个人的经验之谈,希望能给大家一些参考的价值。 大多数情况下,核心游戏系统都比较复杂,牵涉到很多系统之间的协作,也和策划的需求有相当紧密的联系,国外公司一般称这类程序员为Gameplay programmer,国内公司这种职位相对较少,一般就以泛指的客户端程序员代替了,但和做外围系统的程序员不同,真正的Gameplay programmer需要对于AI系统,动画系统,物理系统都有一定的了解,因为这是核心游戏部分都会涉及的领域。正因为核心游戏系统的复杂性,所以必须要有一个适合的,灵活的架构来支持,抛开一些基本的优点,诸如可扩展性,低耦合等等要求不说,我最直观的感受,就是以下两点好处:
好,接下来开始说说设计思路。 解构一个复杂的系统,有一个很好(不是唯一)的办法,就是“分层结构”(Layered structure),也就是把一个复杂系统,分成一层一层的结构,每一层都做每一层自己的事情,并且每一层都是单向依赖。这样可以把一个网状的,如同乱线团一样的复杂系统,梳理的非常的清楚。这样的例子其实很多,比如学计算机的人都很熟悉的OSI网络七层架构,这就是一个非常好的,把复杂问题层次化的典型例子,它使得每一层都可以独立设计,而且可以有明确的设计目标,层与层之间的接口也变得非常清晰。 还有一个游戏的例子,就是游戏的架构,游戏其实也是遵照这层次化的设计思路来设计的,虽然不像OSI那样有一个标准化的结构,但是大部分游戏可以分为核心层(Core),引擎层(Engine),游戏类型层(Game Genre),游戏层(Game),像现在一般的商用的游戏引擎,基本就做到核心层和引擎层,再往上就是使用引擎的人自己设计和实现了,像一些大公司可能会有一些积累,就会根据不同的游戏类型在引擎层的之上抽象出游戏类型层,比如体育类游戏,射击类游戏等等,然后再开始开发实际的游戏产品。这种分层的架构设计就可以帮助我们把复杂的系统进行解构,从而实现每个子系统或者模块的功能单一化。 核心游戏系统架构也可以用这样的思路来设计,这样每一层都可以由不同的人来负责,如果实现的话,在一层当中也可以进行任务分工,那下面我就根据执行顺序,自上而下一层一层来描述。 总共的架构分为五层 第一层:更新/收集世界信息 这部分主要是要设计两个部分,一个是知识池(Knowledge Pool),另一个就是感知器(Sensor)。听上去很高大上,其实概念上很简单,知识池可以理解为就是世界信息的数据存储,比如某一个智能体需要一个这样的数据,“谁是离我最近的人”,这个数据就可以存下来,方便获取,写成代码的话,就类似于这样:
复制代码 这种数据存储的数据结构,可以根据不同的情况去选择,用key-value的黑板格式,或者自定义的数据类型都可以,也可以分成多个知识池来管理不同类型的数据,设计的关键就是要有清晰的世界信息获取方式。 感知器的话,就可以理解为具体的获取数据的方法,可以定义一个感知器的接口类:
复制代码 这样就可以把这个感知器注册到一个感知器的管理器中,当收集所有世界信息的时候,只要遍历一遍这些感知器,就可以完成对于世界信息的收集工作:
复制代码 感知器也可以分为两种,一种是全局的感知器,这种可以看成是对于游戏整个世界,或者关卡的抽象,比如势力图 还有一种是个体感知器,比如听力,视野等等 当然,这只是一种思路,也可以不定义接口,而是写成不同的数据更新方法。这就是第一层,主要的功能就是为下层预备数据。 第二层往下,都是针对单个智能体的更新,也就是说需要对每一个智能体执行更新操作。关于智能体的行为,很多时候容易写的一团糟,又要决策,又要运动,又有动画,还要处理物理,有些系统呢,需要每帧更新,比如位置,有些呢,又不需要更新的这么勤快,比如决策,所以在设计上我把它分成几个层次,决策层,请求层,行为层,运动层。 第二层:更新决策层(做什么)- What to do 决策层就是负责来决策此时该智能体应该要做什么,比如我要走到某个位置,我要攻击,放技能等等,可以说,这就是传统所说的人工智能AI部分,这部分只根据当前所有的世界信息,产生“做什么”的决策,决策的内容会封装在一个“请求”(Request)的结构中,继续向下传递: 这部分的结构可以有多种选择,状态机,行为树,甚至神经网络都可以,但是有两个要点 决策的时机:也就是什么时候进行决策,这里就可以用来控制决策的频率,比如离玩家很远的人可以降低决策频度,离玩家近的人,可以提高决策频度等等,类似与这种的控制都应该在这一层中得到支持和实现。 还有一种特殊的模块是属于这一层,那就是玩家输入,玩家的输入说起来,其实也是一种决策,只是这个决策是通过玩家来做出的。行为树就很容易处理这个情况,将玩家输入和AI决策可以融合成一体让所有的智能体共用: 第三层:更新请求层 上面说到,决策层产生的输出是“请求”,请求是一种自定义的数据结构,包含所以该决策所需要传递的决策信息。那为什么要更新请求层呢?直接把当前请求传递给下一层不就好了吗?这一层的功能抽象,也是我在实践中的经验,总结一句话,“请求层”就类似于一个“防火墙”,由它来“过滤”,那些请求会被继续往下传递到行为层。 我们可以先来看一下请求层的设计,请求层的设计,借鉴了渲染中的“双缓冲”结构,把请求分为,前端请求(Foreground Request),后端请求(Background Request),前端请求就是当前智能体正在执行的请求,因为一个决策请求可能需要多帧才能完成(想象一下,移动到某一个点这个请求,就需要一段时间才能完成),后端请求就是准备执行决策请求,当一定条件满足后,就可以做了一个“Flip”的操作(前后互换),把后端请求变成前端请求,这样的话,后一层就会执行这个请求,从而改变行为了。 细心的同学会发现,在上面的描述中,有一个地方值得回味,就是Flip操作是,“当一定条件满足后”,而这个条件的监测,就是这里更新请求层的时候需要做的事情了,其实每一个决策是存在潜在的优先级的,这个优先级和策划的设计有关,比如我当前正在执行一个攻击的请求,这个时候,新的请求是一个释放技能,此时策划要求,技能释放能够打断当前的攻击行为,那这个判断逻辑就可以写在这一层中,使得当这个条件满足时,可以立即切换请求。这里的设计一般采用配优先级表,和基于规则的(Rule-based)的实现方式。 有了这一层的逻辑抽象,就可以保证它的上层和下层都不需要关心决策能否被执行,而只要关心自身的决策/行为逻辑就可以了,大大降低了上下层的实现复杂度。由于这部分逻辑相对比较繁琐,所以把这些繁琐的逻辑集中在一起,也是一种理想的设计思路。 第四层:更新行为层(怎么做)- How to do 就像补充里所描述的,行为层的职责就是怎么做,也就是如何去完成上层经过决策,经过规则的逻辑判定,最终“胜出”的那个前端请求。像前面提到的寻路,或者选择需要播放的动画,都是在这一层所完成的工作,这层的实现同样可以用行为树,或者状态机,不过我还是推荐用行为树,因为行为树可以扩展和处理更复杂的行为逻辑,比如随机,序列,并行等等。某些请求可能不是用单个行为可以完成的,需要多个行为的配合,比如完成一个技能释放,需要先集气,然后再释放,类似这样的行为,就可以用行为树来实现了,更棒的是,集气这个行为还能被共用。 在这一层中,会产生一系列的输出,有特效,有动画,可能还有声音等等,有一个很重要,也是必不可少的,那就是运动信息(Kinematic Information),这也是智能体最终呈现的样子,这部分内容包括空间信息(位移,旋转,缩放)和动画信息,某些情况下,智能体的空间信息可以通过物理计算在这一层直接更新,动画信息直接调用引擎的播放接口即可,但有时候这种处理还不够,那就需要第五层,运动层的参与。 第五层:更新运动层 游戏中物体的移动有两种方式,一种是动画跟随物理,比如为了解决移动中的滑步问题,我们可以做多个移动的动画,然后根据速度做融合,这样可以调出一个滑步不明显的表现,还有一种就是root motion,也就是物理跟随动画,就是物体的移动和旋转完全跟随动画中的效果,这样可以解决一些物理没有办法模拟的复杂运动。 有些时候,我们需要混合使用这两种方式,并且在位移过程中需要加上一些修正(比如为了解决同步问题),这个时候,就需要用运动层来实现。这一层的输入,就是行为层产生的运动信息,输出自然就是智能体最终的空间信息和动画了。 在实现上,建议对这两种方式进行封装,这样可以对于上层来说,接口就相对统一了。 有了这五层的设计,整个核心游戏系统的更新循环就完成了,并且每一层的功能职责和输入输出都有了明确的定义,如下图: 每一层具体的设计可以仁者见仁,智者见智,并且也和具体的游戏有关,但是整体的架构基本就可以参考这样的思路,至少以我的实践来看,不会导致结构混乱,也可以更好的进行分工和合作。 最后再聊一个关于核心游戏部分网络同步和回放系统的问题(同步和回放是差不多的东西,回放只是把同步的东西存下来而已)。 其实如果有了上面的架构设计,理解网络同步就很简单了。 如果同步放在第二层,那就是采用的“同步输入”(Input synchronization)的方式 如果在第三层,那就是“同步命令”(Command synchronization)的方式 如果放在第四层/第五层,那就是“同步状态”(State synchronization)的方式 这三种方式是越往下传输的数据越多,但是“失同步”(Out of synchronization)的风险就越小。当然不同的方式在具体实现上,还是有很多值得讨论的地方,这里就不多说了。如果客户端和游戏服务器采用相同的语言,那就可以很方便的在单机游戏和网络游戏间切换,在单机模式下,只是本地和本地通信罢了,FPS游戏很多都是这样去实现的,其实在单机模式下,内部也是一个CS的架构,而如果需要一个服务器的版本,只是加一个宏去编译而已。 好了,就说这么多,欢迎讨论,也可以下载那个僵尸的 TsiU_AIToolkit_CSharp.zip (5.97 MB, 下载次数: 7832) ,里面也采用了类似的层次结构,可以参考一下。 相关阅读:从设计者角度谈游戏的架构与细节梳理 |
关注我们官方微信公众号 |
下载我们官方APP-游戏行 |
关注手游动态微信公众号 |
十全干货:核心游戏系统架构设计相关推荐
- 第十二章 网购秒杀系统架构设计案例分析(待续)
······ 转载于:https://www.cnblogs.com/hzzjj/p/9825804.html
- Unity教程之-Unity游戏技能Skill系统架构设计
我想把技能做的比较牛逼,所以项目一开始我就在思考,是否需要一个灵活自由的技能系统架构设计,传统的技能设计,做法都是填excel表,技能需要什么,都填表里,很死板,比如有的技能只需要1个特效,有的要10 ...
- 阿里年薪百万架构师分享「亿级并发系统架构设计」全彩版技术手册,只能说其实高并发不难
什么是高并发? 并发是操作系统领域的一个概念,指的是一段时间内多任务流交替执行的现象 高并发用来指大流量.高请求的业务情景,比如春运抢票,电商双十一,秒杀大促等场景. 高并发的指标有 响应时间:系统对 ...
- 网购秒杀系统架构设计案例分析
大型网站技术架构-核心原理与案例分析 作者:李智慧 申明:文章版权归作者所有,若有侵权,请联系删除 秒杀是电子商务网站常见的一种营销手段:将少量商品(通常只有一件)以极低的价格,在特定的时间点开始出售 ...
- 大数据用户画像系统架构设计
文章目录 一.用户画像数据仓库搭建.数据抽取部分 二.大数据平台.用户画像集市分层设计.处理 三.离线计算部分 四.实时计算部分 五.Solr/ES搜索引擎部分 六.Java Web毫秒级实时用户画像 ...
- 海量并发低延时 RTC-CDN 系统架构设计(下)
上半部分内容:海量并发低延时 RTC-CDN 系统架构设计(上) 低延时 RTC-CDN 系统的架构 传统 CDN 直播发展多年,为了优化延时,业界基本上朝两大优化方向:优化传输层协议和在传输层协议的 ...
- 程序员过关斩将--从未停止过的系统架构设计步伐
" 首先,这篇文章肯定会得罪一些人 " 其次,此文只代表我个人的意见,仅供参考 从分层说起 谈到系统架构的分层和系统领域边界的划分,每个架构师,每个技术经理,甚至每个程序员都有自己 ...
- 准确率100%,阿里商旅账单系统架构设计实践
作者:淸云 阿里商旅作为飞猪旅行旗下面向企业客户的数字化差旅解决方案产品,依托飞猪旅行机票.酒店供应链为企业客户提供一站式的机票.酒店.火车票.用车等预订管控及结算票据服务.阿里商旅不仅是集团欢行的供 ...
- vivo全球商城:库存系统架构设计与实践
作者:vivo官网商城开发团队 - Xu Yi.Yan Chao 本文是vivo商城系列文章,主要介绍vivo商城库存系统发展历程.架构设计思路以及应对业务场景的实践. 一.业务背景 库存系统是电商商 ...
最新文章
- 手机耗电统计app_教你 6 招,解决 iOS13 耗电问题
- 2020年电赛题目,命题专家权威解析!
- 使用JAXP对XML文档进行DOM解析
- spark任务shell运行_大数据系列:Spark的工作原理及架构
- 技术交底软件_【干货分享】软件类产品如何进行专利挖掘与技术交底书撰写?...
- python小型编程_学习Python编程的11个资源
- Go语言学习之11 日志收集系统kafka库实战
- item系列内置方法重构类
- 关于ARINC 573/717帧同步字的误解
- python基础——求两个数的最大公因数和最小公倍数
- 如何设计空白页面,体验更好!
- 10分钟读懂什么是产品定位
- 坚果Pro 电源键失效的处理
- vue单元测试SyntaxError: Unexpected token ‘export‘
- 谁“偷”走了我的雨伞
- android 图形平移 镜子效果 倒影效果
- Linux的文件特殊权限
- 浏览器输入baidu.com加载的过程是什么,听完我的回答和尚摇了摇头,就这?
- 如何逃脱老鼠奔跑试的工作?
- jquery学习2_jquery知识预览
热门文章
- mysql主从复制巡检脚本_mysql主从复制监控shell脚本
- java 流已被关闭_mybatis oracle java.sql.SQLException: 流已被关闭问题
- 力扣——最长公共前缀
- mybatis查询mysql数据库很慢_mybatis查询大量数据库
- cv mat保存图片_EmguCV创建/保存图片
- 安卓gridview条目点击事件_敬业签的安卓手机版设置便签按正序排序教程
- 【Python之旅】第四篇(四):基于面向对象的模拟人生游戏类
- Django 1.10中文文档-聚合
- MongoDB再出安全事故 5800万商业用户信息泄露
- 2017 年大数据、物联网与 AI 的趋势预测