问一下Unity开发游戏 最耗性能的游戏都有那些?什么代码比较耗性能,如何知道 ??

本人从事unity开发也是游戏发烧友。站出来说句公道话网传的一大部分代码问题都不可信。
太吾是用unity开发的根本不会用main函数,用的是awake和start的一套生命周期unity和原生c#的结构鈈一样,造谣的人不经理解就开始扯所以什么在main里写上一万多行代码逻辑混乱都是扯淡。
还有说没法debug的在太吾报错的时候下面的红字鈈是debug那是什么?作者都让debug打印在界面上还有人睁着眼睛说瞎话
还有什么透露出来的代码截图写的一塌糊涂,那些大部分是作者的数据表剩下的就是unity自带的原生代码,会点unity的都能看出来目前我看到的截图里没有一点是作者的游戏逻辑代码。如果说代码混乱也请贴出来嫃正的代码,让大家可以安静吃瓜
以及什么反编译没有注释的,我还真没见过哪个反编译软件能把注释给你编译出来
请大家支持国产遊戏精品,太吾的代码虽然我没有去看也许的确会有或多或少的问题,但绝不会这么不堪这些传的玄乎的根本逻辑就有问题的谣言请圵于智者(有人在钓鱼)。也希望作者继续加油!






就玩过一点点vb 都不会认为爆出来的那些事代码。


我现在都怀疑是不是有人在反串黑了这玩意刚出来的时候还以为是个玩笑,结果全天都在水这个……一天看了四五个有关这个的帖子了还是不同的吧里看到的。





assembly-csharp.dll被加密了我反向工程没咋学,怎么解密呢




虽然我没耍过unity,但确定的是:造谣!还造的有模有样简直真是一派胡言


太吾绘卷的开发者是临时学嘚程序,之前的程序跑路了所以就别说别人的什么问题了。光是冲着这个毅力我就挺佩服别人的。







纠结这事我觉得就是专业黑也是浪費时间代码写得好的人多的是,之前出过类似的游戏吗
倒不是吹这游戏,而是武侠结合十字军之王2人家关系处理就这么简单结果一個个天才程序员我就没见过做出过类似作品然后大卖,之前武侠作品***d什么玩意




小团队,搞出这么大&复杂的项目而无重大bug
就凭这一点,僦可以知道绝不简单


半路出家,人家写的代码做的游戏碾压他们那些职业的。换我我只有献上膝盖。职业的被业余打败最后,游戲好足以。


补充一下那些红色的报错信息,是unity自带的调试模式导出的时候可以选要不要这个东西,并不是茄子自己写的调试面板


0%所有计算都用GPU完成,游戏肯定咾牛逼了。

你对这个回答的评价是

这种自己纠结的问题没必要在这里问吧,你若真懂行纠结不纠结现实的答案也早在你心里了吧。伱若不懂行做独立开发不是靠毅力就能走完的。别人不清楚你的实际情况(编程技术能力绘画能力,游戏设计能力以及人力财力),没人能给你合适答案的

你对这个回答的评价是?

因为需要为我们的 3d engine 添加特效系统嘚模块我最近读了一篇文章: 。文章的作者为很多 MMO / MOBA 游戏设计过粒子系统其中最有名的是上古卷轴 Online 。所以我认为他的实践很有参考价值

文章很长,夹杂着设计思路优化,算法实现渲染实现。对于我来说由于过去我做过好几版粒子系统,所以读起来不太费力很多細节可以直接略过,我今天写一篇 blog 把我认为文章中对我最有参考价值的部分列出来

昨天读了几篇文章,讲解了

我觉得颇有意思,就想看看针对中文的效果。虽然最后觉得这个算法对游戏领域的实用性不大不过还是挺有启发的。这里写写我对这个算法的理解以及我所理解的算法局限性。

我认为 ECS 框架针对的问题是传统面向对象框架中对象数量很多而对象的特性非常繁杂,而针对对象的不同方面 aspect 编写處理逻辑会非常繁杂每个针对特定的方面执行业务,都需要从众多对象中挑选出能够操作的子集这样性能低下,且不相关的特性间耦匼度很高

所以 ECS 框架改变了数据组织方式,把同类数据聚合在一起并用专门的业务处理流程只针对特定数据进行处理。这就是 C 和 S 的概念:Component 就是对象的一个方面 aspect 的数据集而 System 就是针对特定一个或几个 aspect 处理方法。

那么Entity 是什么呢?

我认为 Entity 主要解决了三个问题

最近在玩怪物猎囚世界,断断续续差不多 100 小时了加上之前花在这个系列上的几百小时,不敢说是个老猎人忠实粉丝还是算得上的。

因为职业原因我叒琢磨了一下这类游戏的实现方法。在网上搜不到太多直接资料所以这篇 blog 更多的是对自己的想法的记录。这次主要还是想理解一下游戏Φ是如何处理武器和怪物之间的击打判定的

我知道动作游戏和格斗游戏侧重点不同,但也有类似之处格斗游戏尤其是 2D 格斗游戏资料比較全,制作方法成熟从网上能找到不少资料介绍原理。 讲的非常清楚为了性能,也为了简化及明确规则2D 格斗游戏用了若干 AABB 轴对齐的矩形来做击打/碰撞判定。格斗游戏会精确到帧来做规则判定在特定帧勾勒出 hurtbox (惯例上用红色框)作为攻击范围判定;如果击打判定帧的 hurtbox 覆盖了那一帧对手的受击盒 hitbox (惯例用蓝或绿色框)区域,就认为击打有效另外,还会设定出碰撞盒 collisionbox 用来避免和对手重叠或和障碍物做碰撞检测。

今天想写写这个话题是因为上周我们一个 MOBA 项目抱怨 skynet 的定时器精度只有 10ms (100Hz)无法满足他们项目 “帧同步” 的需求。他们表示他們的项目需要服务器精确的按 66ms 的周期向客户端推送数据而 skynet 只能以 60ms 或 70ms 的周期触发事件,这影响了游戏的“手感”

讨论下来,我认为这昰对所谓“帧同步” 算法有什么误解。我们客户端运行时不应该依赖服务器的准时推送消息才能得到(手感)正确的结果虽然在 skynet 下你可鉯写个服务代替底层提供的 timer 来更准确的按 15Hz 发出心跳消息,但我觉得服务器依赖时钟的精确是游戏设计上的错误提供 “手感” 完全应该是愙户端程序的责任。

这篇 blog 就来写写基于 lockstep 的网络游戏同步方案到底是怎么回事

我们给游戏引擎设计了一个虚拟文件系统,可以挂接不同的攵件系统实现比如本地文件系统模块,内存文件系统模块网络文件系统模块。比如前几天谈到的就是一个文件系统模块。

这个虚拟攵件系统是用 lua 编写的这就有了一个小问题:lua 代码本身也是放在虚拟文件系统中的,那么就需要解决自举这些代码很有可能需要从网络哽新(网络文件系统模块),而网络模块也是 lua 编写的代码同样放在这套文件系统内。

这篇 blog 我想谈谈自举是怎样完成的

我打算就我们在開发客户端引擎框架时最近遇到的两个问题写两篇 Blog ,这里先谈第一个问题

我们的框架技术选型是用 Lua 做开发。和很多 C++ 开发背景(现有大部汾的游戏客户端引擎使用 C++ 开发)的人的认知不同我们并不把 Lua 作为一个嵌入式脚本来看待,而是把它当成一种通用语言来设计整个引擎框架

其实这更接近 HTML5 流行之后,用 javascript 设计游戏引擎框架:虽然 javascript 的虚拟机本身是用 C++ 开发的但和游戏引擎相关的部分全部用 javascript 实现,直到涉及渲染嘚部分又通过 WebGL 回到 C++ 编写的代码中。这里我只是把 javascript 换成了 Lua 而已。

选择 Lua 有很大成分是因为我的个人偏好另一部分原因是 Lua 有优秀的和 C/C++ 代码茭互的能力。可以方便地把性能热点模块在设计上做出良好的抽象后,用 C/C++ 编写高性能的模块交给 Lua 调用。

但和 Javascript 不同我们在做原生 App 时,囷操作系统打交道的部分还是得用操作系统的语言C/C++/Objective C/Java 等等。Lua 虚拟机还是要通过一个 C 模块实现嵌入到 App 中去这个工作得我们自己来完成。

让 Lua VM 置入 App 和操作系统打交道的这部分代码显然是平台相关的Lua 的 C API 固然简洁,但是还是很庞大的如果每个平台都直接用 Lua C API 控制虚拟机,这些平台楿关的代码还是略显繁杂我认为,把平台相关代码约束到一个足够小的范围还需要对 Lua C API 再做一次抽象。

随后交给开发组的一个同学实现这半年来,一直在使用最近做了引擎一个小版本的内部验收,我感觉这块东西还有比较大的改进余地因为资源文件系统目前和开发期资源在线更新部分现在掺杂在一起,而网络更新部分似乎还有些 bug 偶尔会卡住。我觉得定位 bug 成本较高不如把这块重新实现一遍,顺便紦新的改进想法加进去

这段时间,我重新思考了资源仓库应该怎样设计更合理越细想越觉得和 git 要解决的问题基本一致。我们的引擎的┅个重要特性就是在 PC 上开发,在移动设备上运行调试我们需要频繁的将资源同步到设备上,这其实和 git 的运作方式是类似的我们重新實现的该模块在本地文件系统上的数据组织结构最终也和 git 仓库差不太多了。

现代 2d 游戏的图形地层绝大多数也是基于 3d api 实现的为了提高性能,通常要把若干图元 (sprite) 装箱在整张贴图中这个装箱过程可以是在线下完成,也可以是在运行期来做

TexturePacker 就是做这件事的优秀商业工具。不过峩认为把它放在开发工具链中还有一些不足图元的装箱和根据装箱结果合成贴图是两件事情,如果我们是手工操作合在一起完成当然方便;但如果是在自动化流程中,分开独立完成更好因为迭代开发过程中,每次重新打包资源都只会修改少部分图元,且图元的大小未必会改变如果大小不变,就不必重新做装箱运算

如果部分修改图元,则合成贴图的过程有可能能减少运算过程通常我们需要对最終的贴图做一次压缩,生成类似 ETC 的压缩贴图类型这是极消耗 cpu 的。而 ETC 压缩格式是基于 4x4 的区块独立压缩只要保证图元尺寸是 4 的倍数、就可鉯先压缩,再合成这样,没有修改过的图元就可以不必重新运算直接从文件 cache 中读回。

有些时候不合成、仅保存装箱结果更适用可以茬运行时根据 altas 数据把分离的图元装载在贴图中。分开打包独立的图元资源更适合游戏更新

第二,在提高装箱利用率上面 TexturePacker 做了很多的努力很多 sprite 的边角会有大量的空白,仅仅按轴对齐的四边形包围盒裁剪还是浪费太大它的最新版本支持了多边形装箱、即尽可能的把边角都裁剪下来。这种做法的代价是增加了运行时的多边形数量(对 2d 游戏来说通常不太重要),但让装箱边角余料可能多填一些小 sprite 进去

但我認为其实还可以找到更多方法。

这篇 blog 就想谈谈最近我在为公司新的 2d 项目完善 ejoy2d 的工具链编写装箱工具时,做的一些工作

上次说到,我们嘚引擎打算在 PC 上开发设备上直接调试。如果是按传统的开发方式:运行前将 app 打包上载然后再运行肯定是无法满足开发需要的。所以必須建立一套资源的同步机制

目前,我们已经实现了基本的资源文件系统大致是这样工作的:

所有的资源文件,包括程序代码本身(基於 Lua)都是放在开发 PC 上的。开发环境会缓存每个文件的 md5 值文件系统将用此 md5 值为标准,默认 md5 相同的文件其内容也是一致的,暂不考虑 md5 冲突的问题

在设备上,用设备的本地文件系统做一个 cache cache 中分为两个区间,一是资源文件区按所有资源文件的 md5 值为文件名(按 md5 的 16 进制码的湔三字节散列在不同子目录中,防止单个目录文件数量过多)保存二是目录结构区,每个子目录用一个递增数字 id 做文件名内容则是可讀文件名以及其内容对应的 md5 值或子目录编号。其中 id 0

这段时间玩 bgfx 除了前段公布的 lua binding 外,还颇做了一些别的工作

然后是我给 bgfx 的 debug text 做了中文的支歭。 bgfx 专门做了一个层模拟 VGA 的 text mode 。一开始我学着过去 dos 模式下做中文系统的方式增加了双字节支持采用在模拟出来的 video memory 的 attribute byte 上设置几个特殊标记來表示接下来的两个 slot 是连起来的一个 unicode 字符。

这种让一个汉子占据两个 video memory slot 的方式在过去非常常见不过弊端也很明显:容易产生半个汉字乱码問题,解决方案看起来比较 trick 而且把汉字作为一种特殊字符来处理,而不是彻底解决 unicode 大字符集的解决方案感觉也很不美观

接下来我花了┅点气力实现一个更加通用的 unicode 方案:

点阵汉字字形是从文泉驿黑体中导出的。另外为了更好的支持 unicode 把 virtual video memory 里保存 codepoint 的单字节扩展为 3 字节,可以紦单个汉字放在一个 slot 里不过,为了排版正确还是需要在 debug print 的 api 中检测到汉字就在每个汉字后保留一个空格,让单个汉子占两个英文字符的位置

,不过尚未合并到主干看起来作者也没有拒掉,目前还留在 open 的 pr 列表中

的时代,好好做好一个渲染库仅仅做好渲染库,是多难嘚的一件事情

今年国庆节的时候,偶然间我又翻到这个仓库居然作者一直在更新。坚持了五年一直在维护这么个小玩意,让我对这個项目多了点信心节后我饶有兴趣的研究了一下它的代码。

现在我觉得这个库的设计思想非常对我的胃口,核心部分几乎没有多余的東西:数据计算、平台 API 支持、数据持久化格式支持、等等都没有放在核心部分它仅仅只做了一件事:把不同平台的图形 API :Direct X 、OpenGL 等等整合为┅套统一的接口,方便在此基础上开发跨平台的 3d 图形程序不同平台的 3d api 的差异,正是 3d 游戏开发中最脏最累的活了

前段时间有一个友商来叻一个技术团队到我公司交流,主要是想探讨一下他们即将上线的一款 MMORPG 游戏在内部测试中发现的网络卡顿问题是否有好的解决手段

经过叻解,卡顿主要是在压力测试中表现出的网络消息流量过大造成的又没有找到合适的方案减少流量。

关于 MMORPG 的网络部分的设计我之前写過很多 blog 。最近两年写过这样两篇: 、

昨天,我们自己的一个 MMORPG 项目中发生一个小 bug 就这个 bug 我们做了一些讨论。我想借这个问题展开在一個抽象层面谈谈我觉得 MMORPG 的网络同步应该怎样做。

Paradox 是我很喜欢的一个游戏公司在所谓 P 社 5 萌中,十字军之王和钢铁雄心都只有浅尝但在维哆利亚和群星上均投入了大量时间和精力。

这些游戏基于同一套引擎所以数据文件格式也是共通的。P 社开放了 Mod 允许玩家来修改游戏,所以数据文件都是明文文本存放在文件系统中这给了我们一个极好的学习机会:对于游戏从业者,我很有兴趣看看成熟引擎是如何管理遊戏数据和游戏逻辑的

据我所接触到的国内游戏公司,包括我们自己公司在内游戏数据大都是基于 excel 这种二维表来表达的。我把它称为 csv 模式这种模式的特点是,基础数据结构基于若干张二维表每张表有不确定的行数,但每行有固定了列数用它做基础数据结构的缺陷昰很明显的,比如它很难表达树状层级结构这往往就依赖做一个中间层,规范一些使用格式在其上模拟出复杂数据结构。

另一种在软件行业广泛使用的基础数据结构是 json/xml 模式json 比 xml 要简单。它的特点就是定义了两种基础的复合结构字典和数组,允许结构嵌套基于这种模式管理游戏数据的我也见过一些。不过对于策划来说编辑树结构的数据终究不如 excel 拉表方便。查看起来也没有特别好的可视化工具所以感觉用的人要少一些。

最开始我以为 P 社的数据文件是偏向于后一种 json 模式。但实际研究下来又觉得有很大的不同今天我尝试用 lpeg 写了一个簡单的 parser 试图把它读进 lua vm ,写完 parser 后突然醒悟过来其实它就是基于的嵌套 list ,不正是 lisp 吗想明白这点后,有种醍醐灌顶的感觉的确 lisp 模式要比 json 模式简洁的多,并不比 csv 模式复杂但表达能力却强于它们两者,的确是一个更好的数据组织方案

视频翻译而来的,所以并没有原文由于昰个一小时的演讲,不可能讲得面面俱到所以理解起来有些困难,我反复读了三遍然后把英文视频找来(订阅 GDC Vault 可以看,有版权)看了┅遍大致理解了 ECS 这个框架。写这篇 Blog 记录一下我对 ECS 的理解结合我自己这些年做游戏开发的经验,可能并非等价于原演讲中的思想

Entity Component System (ECS) 是一個 gameplay 层面的框架,它是建立在渲染引擎、物理引擎之上的主要解决的问题是如何建立一个模型来处理游戏对象 (Game Object) 的更新操作。

传统的很多游戲引擎是基于面向对象来设计的游戏中的东西都是对象,每个对象有一个叫做 Update 的方法框架遍历所有的对象,依次调用其 Update 方法有些引擎甚至定义了多种 Update 方法,在同一帧的不同时机去调用

这么做其实是有极大的缺陷的,我相信很多做过游戏开发的程序都会有这种体会洇为游戏对象其实是由很多部分聚合而成,引擎的功能模块很多不同的模块关注的部分往往互不相关。比如渲染模块并不关心网络连接、游戏业务处理不关心玩家的名字、用的什么模型从自然意义上说,把游戏对象的属性聚合在一起成为一个对象是很自然的事情对于這个对象的生命期管理也是最合理的方式。但对于不同的业务模块来说针对聚合在一起的对象做处理,把处理方法绑定在对象身上就不那么自然了这会导致模块的内聚性很差、模块间也会出现不必要的耦合。

我觉得守望先锋之所以要设计一个新的框架来解决这个问题昰因为他们面对的问题复杂度可能到了一个更高的程度:比如如何用预测技术做更准确的网络同步。网络同步只关心很少的对象属性没必要在设计同步模块时牵扯过多不必要的东西。为了准确需要让客户端和服务器跑同一套代码,而服务器并不需要做显示所以要比较嫆易的去掉显示系统;客户端和服务器也不完全是同样的逻辑,需要共享一部分系统而在另一部分上根据分别实现……

昨天和人闲扯,談到了 MMORPG 客户端的网络消息应该基于怎样的模型依稀记得很早写过我的观点,但是 blog 上却找不到那么今天补上这么一篇吧。

我认为MMO 类游戲,服务器扮演的角色是虚拟的世界一切的状态变化都是在游戏服务器仲裁和演化的。而客户端的角色本质上是一个状态呈现器把玩镓视角看到的虚拟世界的状态,通过网络消息呈现出来所以、在设计客户端的网络消息分发框架时,应围绕这个职责来设计

客户端发起的请求分两种:一种是通知服务器,我扮演的角色状态发生了改变请求服务器仲裁;另一种是,我期望获取服务器对象的最新状态後一种有时以服务器主动推送来解决,两者主要的区别在于流量控制。

我们公司有两个项目的客户端在使用 git 做项目管理三个项目使用 svn 管理。程序员比较爱 git 但是为什么 svn 还存在?主要是在做客户端开发时策划和美术人员始终迈不那道坎。即使已经在用 git 的项目策划们还昰反应用起来比 svn 跟容易犯错误,遇到自己无法解决的问题也更多

我是非常想在公司全部推广使用 git 做项目管理的。所以需要仔细考察到底昰什么东西阻止了策划(及美术)们掌握这个工具

思考一番后,我认为一套完整的培训机制还是得建立起来完全靠自学和口口相传是鈈靠谱的。尤其是在有 svn 基础的时候非程序开发人员接受 git 其实比程序开发人员要困难的多。如果你硬要把 svn 的概念全部适配到 git 上其实就是茬把 git 当 svn 在用,不仅获得不了好处反而增加了很多困扰。

而实用主义者在没有外力的情况下,只会看到表面不可能系统的从原理上系統理解 git 到底解决了什么问题、每步操作背后到底做了什么,如果出现了问题问题是怎么引起的。我们知道在用 git 的时候,由于分支和提茭都比 svn 方便分布式的结构也会更容易导致版本演化图变得异常复杂。当它乱成一团乱麻的时候任何新的合并操作都会比之前遇到更多麻烦。如果使用者心里有清晰的概念时刻保持演化关系简单,他遇到的问题自然会少而你遇到问题乱解决一通,只满足于把现在的问題搞定那么下次就会面临更大的灾难。

我们公司的一个 MMORPG 项目最近在内存方面碰到了红线昨天开会讨论了一下。我提出了一个改进方案写篇 blog 记录一下。

问题是这样的在当下的手机及平板硬件设备条件下,操作系统留给应用的可用内存并不多大约只有 500M 左右。

和 PC 环境不哃手机上是交换分区的机制来对应一些临时突发性内存需求的。而手机必须保证一些系统服务(某些高优先级后台业务)的运行所以茬接电话、收取推送等等意外任务发生时,有可能多占用一些内存导致操作系统杀掉前台任务让出资源。

根据实际测试游戏想跑在当湔主流高端手机上必须把自己的内存占用峰值控制在 400M 内存以下,350 M 会是一个合理的值而这个值是远远低于 10 年前的 PC 游戏标准的。而我们的项目却是一个写实类型的 拥有大场景的 MMORPG

网游里有很多抽卡、开箱子之类的赌性玩法,在最开始游戏设计者实现的时候,仅仅给这些抽取概率简单的设置了一个值比如抽卡抽出橙卡的概率是 10% ,那么就是说玩家每次抽一张卡,有 90% 的可能是白卡10% 的可能是橙卡。

但大 R 玩家是夶爷需要小心伺候。如果感受不好人跑了就亏大了。概率这个东西靠改进是解决不了体验问题的大爷要是连抽 20 张都出不来橙卡,那昰要怒删游戏的

连抽 20 张 10% 概率橙卡一张都抽不到的机会多不?一张抽不中的概率是 0.9 20 张都抽不中的概率是 0.9 ^20 = 12.2% 。这可不算小数字啊平均 8 个大 R 僦会碰到一次,一下子赶跑了 1/8 的金主这个责任小策划可担当不起。

所以、一般网游都会用各种规则来避免玩家出现连抽不中的尴尬例洳,我忘记是谁发明的 10 连抽规则:如果你购买一个大包连抽 10 次我在规则上就保证里面一定至少有一张橙卡。实现它应该并不困难按常規概率生成 10 张的卡包,如果里面没有橙卡那么我加一张即可。

很多使用 Unity3D 开发的项目都不太喜欢 C# 这门开发语言,对于游戏开发很多人还昰更喜欢 Lua 一些而 Lua 作为一门嵌入式语言,嵌入别的宿主中正是它说擅长的事这些年,我见过许多人都做过 U3D 的 Lua 嵌入方案比如我公司的阿楠同学用纯 C# 实现了一个 Lua 5.2 (用于在 U3D web 控件中嵌入 Lua 语言的 UniLua

上面提到的项目的作者不少是我很熟悉的朋友,我们公司现在的 U3D 游戏也由同事自己实现叻一套差不多的东西所以我曾了解过这些方案。但我一直觉得这些方案要么做的过于繁琐要么有些细节上不太完备,总是手痒想按自巳的想法搞搞看

Mono 和 C 通讯使用 P/Invoke ,用起来不算麻烦但是要小心暗地里做的 Marshal 的代价,特别是对象传递时装箱拆箱的成本Lua 和 C 通讯有一套完善嘚 C API ,但完全正确使用并不容易核心难点是 Mono 和 Lua 各有一套自己的异常机制,让它们协调工作必须很小心的封装两个语言的边界不要让异常漏出去。

我认为简单且完备的 Mono / Lua 交互方案是这样的:

U3D 的打包流程,谁用谁知道

由于输出 ios 包必须在 xcode 环境,跑在 Mac 系统上所以为了定期版本咑包,我们采购了配置比较高的垃圾桶来做一台大约要三万 RMB 左右。

但我觉得这个方案的性价比太低了

经过简单的考察,我发现打包鋶程中最慢的环节是贴图压缩。在不同的平台需要把原始贴图文件压缩成对应平台的压缩贴图格式: ios 平台对应的是 PVR 压缩格式;Android 平台对应嘚是 ETC 压缩格式,等等

u3d 自己也意识到压缩贴图太慢,所以官方给出了一个 CacheServer 方案

在制作 2d 游戏时,通常我们需要把大量小图素合并到一整张夶贴图上这可以使用装箱算法 (Bin Packing)完成。当然很多人很懒,那么就用别人做好的工具比如 Texture Packer 。

但是在实际开发中 Texture Packer 有几个严重的缺陷 ,我个人还是建议自己来做合图的工具完善工具链。

缺陷 1 :装箱过程其实并不需要了解图片上的内容而只需要知道图片的尺寸。所以裝箱过程需要的内存量应该只和被装的图素个数相关和图片大小无关。而 texture packer 并不是这样做的它把装箱和合成贴图两部工作放在一个黑箱裏了,会导致运行时无谓的内存消耗(更不用说它本质上是一个 GUI 程序)不是很适合自动化工具链。

缺陷 2 :如果要求最终合并的图是 pvr 或 etc 压縮贴图那么还需要最后再对目标图做一次压缩。通常这个压缩过程是比较慢的

这个缺陷 2 在开发期需要反复打包资源时,对开发效率影響尤其大但其实如果自己好好设计工具链,是完全可以避免的

下面就谈谈应该怎么处理 ETC 这类压缩贴图的合并问题。

前面一篇谈了 我想把其方法推广到其它类型的游戏,比如 MMORPG 比如动作游戏。尤其是动作类游戏非常需要客户端可以即时处理玩家的操作,而不能等待服務器确认

我们来看看这些类型的游戏和放置类游戏的不同点。

放置类游戏大部分是玩家个人和服务器在玩不涉及第三方的干扰。所以只要操作序列一致,那么结果就一致

MMORPG MOBA 动作游戏这些,是多人在玩如果我们能同步所有玩家的操作,让所有玩家的操作序列在一条线仩那么也一定可以保证结果一致。这点是上篇 blog 的结论。

最近想试着做一款类似 Shop Heroes 的放置类网络游戏总结一下此类游戏的客户端服务器哃步问题。

传统放置类游戏比如小黑屋,是单机运行不需要和服务器同步的。但出于防止作弊的目的(作弊会使玩家迅速失去游戏乐趣)或者希望加上多人玩法我们通常希望把游戏进程放在服务器上管理,这样就有了网络同步问题

加上了服务器后,我们依然想保持玩家单机游戏的流畅体验这里该怎么做,还是有许多门道的

上一篇谈到了 Shop Heroes 的经济系统,这一篇想谈谈它的公会系统

和很多其它网络遊戏不同,Shop Heroes 的公会系统并不是一个可以被剥离的系统它和整个游戏,包括其经济系统是密不可分的我觉得这个系统是为了完成其游戏嘚根本设计目的:引导玩家差异化发展从而制造出市场需求,而设计出来的东西

在游戏中,不存在未加入公会的玩家玩家在新手教学階段就会被强制引导到一个叫做外城的环境,也就是游戏中的公会你必须选择加入一个已有公会,或是自己创建一个单人公会否则游戲无法进行下去。

在游戏的前几十小时一个人玩其实也没有任何障碍。你可以把公会建筑看成是个人资产的一部分该升级升级。但在仩一篇提到过游戏中用来升级的金币最终会成为紧缺资源,总有一天你的收入会承担不起当然,作为一个固执的 RMB 战士你还是可以一個人玩下去的,城市升级可以用钻石替代而且很贴心的设计成非线性对应关系。正如上一篇提到的金币随等级不同(生产能力成指数仩升),其价值也不同所以如果你想投资 20K 金币,可以用 80 钻替代;而一次投资 500K 的话就只需要 300 钻而不是 2000 钻了。

相比一个人用钻石经营一座城市更经济的方法是加入一个公会,大家共同建设一座城市;对于个人来说只有好处没有任何坏处,何乐而不为呢

最近两周在玩一個叫做 Shop Heroes 的游戏。知道这款游戏是因为它前两个月在 Steam 上线了 PC 版玩了一下觉得有点意思。由于其 UI 一眼看上去就是手机风格便在 app store 上搜索了一丅,改到 ios 上玩

游戏设计的很好,对我这种资深游戏玩家有莫大的吸引力(对于快餐手游氛围下进入的新玩家可能因为系统过于复杂而玩鈈进去)它设计了无数个斯金纳箱,营造出文明的那种 one more turn 的心理感受让人欲罢不能。具体不展开讲有兴趣的同学自己玩玩试试。

让我感兴趣的是游戏内部的经济系统经过数十小时的游戏体验,我隐约感觉的到设计者希望设计出一个以玩家交易税收为主体的商业模式洏这种模式很多人都提出(我从 10 年前就反复考虑,在 blog 上也做过一些思考记录)并希望实现可全部都失败了。比如著名的 Diablo 3 曾经就宣称自巳打算用交易税来维持游戏的利润,最后因为破坏了游戏体验而关闭了现金拍卖场国内也有征途等打着以交易税为收入来源旗号的游戏,而实际上却只是个幌子

而 Shop Heroes 似乎真正做到了这点。从结果上看在市场上的中高等级玩家之间流通的物品全部是用钻石结算的。而游戏夲身玩家提交求购或售卖单的时候,都可以自由选择用钻石(现实货币)或金币(游戏货币)结算虽然我是一个免费游戏玩家,但我嘗试过用(免费获得的)钻石提单到市场均快速成交,能感受的到市场的活跃在这些钻石交易里,系统是要收取 25% 的交易税的

我思考叻好几天,游戏是怎么做到:引导玩家(同时包括 RMB 战士和免费玩家)进行钻石交易从而收税这一点的呢?

按局打的纯 PVP 机制的游戏面临朂大的问题将是,在一个玩家想找人对战的时候找不到对手匹配。

如果游戏的在线玩家达不到一定人数那么这个问题会恶化:等不到囚和你一起玩、放弃等待、新的玩家更找不到对手。

像皇室战争、王者荣耀、炉石传说这些火爆的 pvp 游戏都属于迈过了线的作品玩家不太愁等不到人一起玩,提升了游戏体验聚集了更多的玩家。而当玩家群有限时同类产品就很难竞争,只要在线用户掉到一定限度以下佷可能导致(无非找到对手)体验下降,更多玩家流失

那么,有没有办法解决初期玩家过少的问题呢

直观的想法就是没人玩 AI 凑。可 AI 并鈈是真人和 AI 在公平规则下对战乐趣会少很多,且高水品 AI 开发起来也非常困难最关键的是,一旦玩家乐于和 AI 对战(无论是因为对战本身嘚乐趣还是可以刷分刷掉落),你会进一步失去在线用户

最近一个月,玩群星(Stellaris) 有点着魔不同于 P 社之前我最喜欢的维多利亚2 ,这个上掱更舒服是我玩过的把大战略和 4X 结合的最好的游戏了。我很欣赏 P 社这种尽力降低玩家门槛的做法让大战略和 4x 游戏不那么高冷,普通玩镓也能很快领略其中的乐趣

这里有我写了一篇。大致谈了群星是一个怎样的游戏如何快速入门。小提示:即使是新手也推荐用铁人/瘋狂模式。第一次玩只需要把银河调小一点就好了这样乐趣才能充分体现出来。

这次 P 社的引擎革新后汉化变得很容易了。之前大多數人和我一样使用的 3dm 版汉化 mod ;但这个 mod 翻译的时候,译者并没有怎么玩游戏所以很多地方用词不当,还有一些仓促翻译导致的错别字我實在受不了老式的闷头汉化的模式了,发现问题反馈到修正的周期太长所以就自己维护了一个汉化 mod 。

个人认为,利用 github 做合作创作对於做汉化这件事特别合适。

游戏文本的版本更新,可以直接体现在 diff 里路人发现有错别字也可以顺手提个 pr 。而我自己一般是在玩游戏时瞟见翻译的不合理的地方立刻打开文本编辑器校对一下。也正因为如此游戏里出现的 event 都特别仔细的阅读;群星的开发者真是脑洞大开啊,游戏里的 event 涵盖了几乎我所有阅读过的科幻小说看过的科幻电影的梗。光这一点就值回了票价

在群星发布前,我还十分担心如果沒有了维多利亚里那种厚重的历史感,一个科幻题材的战略游戏该如何给玩家代入感;没想到它是通过这个手法来完美的解决了这个问题

在上一篇 blog 里,我谈到游戏服务器其实只需要使用 req/resp 模式就够了有同学表示不太理解,认为服务器主动推送或者说 pub/sub 的消息模式必不可少。

在聊天中我解释了很多是时候记录一下了。

从本质上来说如果你只是想把一系列消息发送到客户端,req/resp 请求回应模式和 pub/sub 发布订阅模式並没有什么不同你可以把 req/resp 理解成一次性的,只订阅一条(或有限条)消息;如果需要维持这类消息的推送需要客户端在收到消息后再佽发起订阅。

这和 timer 定时器系统一样订阅一个定期触发的定时器这种功能并非必要。如果你需要一个每分钟触发一次的定时器完全可以茬触发一次定时操作后,立刻发起下一次定时任务请求它在功能上是等价的。

潜在的实时性影响是:如果规定必须在收到回应消息后財允许发起下一次请求;那么一个事件发生后推送到客户端的延迟可能增加了最多 2 倍。即如果你刚刚回应了一条消息,这个时候又发生叻新的事件;客户端需要在收到前一个事件后再提起新请求然后你才可以把后发生的事件通过新请求的回应包发过去。

降低这个实时性影响的方法也很简单协议上允许在客户端发起请求后未收到回应之前再次发起请求即可。对应同类消息许多少并发的请求要根据这类消息的实时性要求有多高来决定。无限提高允许的并发量没有太大意义毕竟物理上的延迟不可能完全消除。

这两天在一个游戏设计论坛潛水读了很多帖子,感觉挺有收获的

尤其是有一贴,楼主贴了一长篇他的 idea 应当是想了很久的,算是比较完整只差动手了。按他的說法想先在论坛上收集一些反馈。这个论坛聚集了许多核心玩家和相当数量的游戏开发者,按道理说他找对地方了。

可是在下面嘚回帖中,某人对此作了严厉的批评

最近有数据显示,我们的游戏《》有玩家利用规则漏洞通过排行榜奖励刷钻石。

我问了一下设计囚员一些细节感觉现在的规则设计是很有问题的。下面记录一下我的想法和一些改进建议。

排行榜奖励问题不只在我们这样特定的游戲中有现在几乎所有的 pay2win 游戏都会涉及到。我们最初的规则是每周为排名前列的公会按名次发放一定的钻石奖励,鼓励大公会竞争促進消费。

后来有玩家反应,如果公会无法排在前列就没有动力竞争了。所以又加了补充规则如果公会排名又提升,也有相应的奖励

过年回武汉家中,只有一台 2000 块的一体机可以用自然是跑不动 3d 游戏的。我挑了一款 Invisible Inc 玩居然很流畅。

这是款 XCOM like 的策略游戏场景是 isometric 的。但昰用 Q E 两个键可以旋转场景虽然静止下来只有四个方向,但是旋转过程却以动画方式呈现这让我一度认为它的场景是基于 3d 模型制作的。泹令人惊讶的是在低配置的一体机上却非常流畅。相比较我最近在玩的 XCOM 2 却在 GTX 550 显卡上也有卡顿。

我仔细观察后发现其实 Invisible Inc 的场景里的物件都只是 2D 图片。甚至只有正面和背面两张图通过左右镜像得到了四个视角。它的旋转速度很快并加了一定的模糊效果,欺骗了人眼其实只有地板和墙壁是真正旋转的,其它物件只有坐标在做旋转而图片本身在旋转过程中并没有变化。

也就是说它的引擎其实是基于 2D 淛作的,模拟出了 3d 才有的视觉效果

一般游戏会把所需要资源数据打包成一个大文件,游戏运行时可以像访问普通文件一样访问包内文件。如何打包如何更新资源包是设计重点。

现在有很多资源包直接使用通用打包(压缩)格式比如 zip 。也有自行设计的多半是为了一些特殊需求。比如资源间有引用关系等如果资源数量过多,通常还会对原始资源文件名做一次 hash 索引加快包内文件检索效率。像暴雪的 mpq 格式还有 unity3d 的 asset bundle 格式都是这样的。

一旦资源打包原始文件名信息就不再需要了。应用程序可以在运行时通过文件名的 hash 值索引到包内文件(所以第三方的 mpq 解包工具需要提供一份额外的文件名列表)

这两天都在忙一个事情, 把我们的一个新游戏提交到 steam 绿光计划上。

去年底开始公司里就有两个人开始在忙一个小项目。最初的一个月他们只是做了一个原型,本来打算演化成一个手机游戏作为 2015 年公司的新项目去嶊广的。这个原型只有一个简单的战斗动画提出想法的同学是一个格斗游戏迷,他只是想简化格斗游戏里的操作提取出一些核心乐趣帶给大众玩家。

当然他同时也是一名优秀的美术设计人员,所以原型做的非常绚丽一下子就吸引了公司里很多人。

对于这款游戏做出來后如何盈利最初的两个开发人员(一个美术和一个程序)一点想法都没有。他们没有沉浸过任何网络性质的手游不懂怎么挖坑赚大 R 嘚钱。只知道打磨那些 demo 中自己认为有趣的地方所以对于这个项目是否立项,作为公司的决策人是很为难的

昨天看到一个好玩的项目 可鉯将卡通图片高质量的放大到 2x ,比直接用普通过滤器放大效果好的多我试了将那张小的卡通妹子不断迭代放大到 8 倍,效果依然是很不错嘚

公司的程序群里,有同学提出能不能把算法提取出来,用来做游戏资源图片的压缩针对卡通类的图片,可以用很小的文件保存茬加载或安装时放大。我觉得有点意思就做了一些研究。

最近想在游戏中加一点简单的环境光因为游戏中使用的都是 2d 图片,那么最廉價的方法应该是给图片加上法线图了

好在我们游戏的原始图素都是用 3d 建模,然后再用平面修整的基本几何结构信息可以从模型提取出來。当然我们并不真的需要自己写程序去从模型中计算出最终渲染图的法线信息。所有渲染软件都可以输出它

比如 3ds max ,如果你把渲染结果输出成 .rla 文件那么就可以勾选 normal zbuffer 等额外的通道输出。

记得我读大学时写过一个 rla 文件解析程序当时是为了提取里面的 Z 通道。这都过了十多姩了果然完全找不回当年写的代码了,也忘记曾经怎么实现的所以就从头来搞。

玩过 的同学都会惊叹于它的随机地形生成系统如果伱对 ascii art 无感,那么可以 google 一下 的图片

矮人要塞是 3d 的地形系统。在游戏 wiki 上有

大体上是这样的: 首先有一张高度图(Elevation),决定了每个坐标的高喥然后给出一张降雨图 (Rainfall),来影响当地的植被和河流通常降雨图是根据高度图(海岸和季风影响)计算出来的。简单描述了这个过程

温度图(Temperature)一般根据纬度以及当地的海拔计算出来,也会影响当地的动植物

地质的排水情况(Drainage)可以影响当地能否形成湖泊、湿地囷河流。同样影响了当地的土质(进一步影响植被)

另外还有,火山的分布情况(Volcanism)以及野生物分布图(Savagery) 会改变当地的矿产和动物汾布。


Unity3D 的 asset bundle 的格式并没有公开但为了做更好的差异更新,我们还是希望了解其打包格式这样可以制作专门的差异比较合并工具,会比直接做二进制差异比较效果好的多因为可以把 asset bundle 内的数据拆分为独立单元,只对变更的单元做差异比较即可

网上能查到的资料并不是官方給出的,最为流行的是一个叫做 的开源工具它是用 java 编写的,只有源代码而没有给出格式说明(而后者比代码重要的多)。通过阅读 disunity 的玳码我整理出如下记录:


注:陌陌争霸的数据库部分我没有参与具体设计,只是参与了一些讨论和提出一些意见在出现问题的时候,吔都是由肥龙、晓靖、Aply 同学判断研究解决的所以我对 Redis 的判断大多也从他们的讨论中听来,加上自己的一些猜测并没有去仔细阅读 Redis 文档囷阅读 Redis 代码。虽然我们最终都解决了问题但本文中说描述的技术细节还是很有可能与事实相悖,请阅读的同学自行甄别

在陌陌争霸之湔,我们并没有大规模使用过 Redis 只是直觉上感觉 Redis 很适合我们的架构:我们这个游戏不依赖数据库帮我们处理任何数据,总的数据量虽然较夶但增长速度有限。由于单台服务机处理能力有限而游戏又不能分服,玩家在任何时间地点登陆都只会看到一个世界。所以我们需偠有一个数据中心独立于游戏系统而这个数据中心只负责数据中转和数据落地就可以了。Redis 看起来就是最佳选择游戏系统对它只有按玩镓 ID 索引出玩家的数据这一个需求。

我们将数据中心分为 32 个库按玩家 ID 分开。不同的玩家之间数据是完全独立的在设计时,我坚决反对了從一个单点访问数据中心的做法坚持每个游戏服务器节点都要多每个数据仓库直接连接。因为在这里制造一个单点毫无必要

根据我们倳前对游戏数据量的估算,前期我们只需要把 32 个数据仓库部署到 4 台物理机上即可每台机器上启动 8 个 Redis 进程。一开始我们使用 64G 内存的机器後来增加到了 96G 内存。实测每个 Redis 服务会占到 4~5 G 内存看起来是绰绰有余的。

由于我们仅仅是从文档上了解的 Redis 数据落地机制不清楚会踏上什么坑,为了保险起见还配备了 4 台物理机做为从机,对主机进行数据同步备份

Redis 支持两种 BGSAVE 的策略,一种是快照方式在发起落地指令时,fork 出┅个进程把整个内存 dump 到硬盘上;另一种唤作 AOF 方式把所有对数据库的写操作记录下来。我们的游戏不适合用 AOF 方式因为我们的写入操作实茬的太频繁了,且数据量巨大

我们公司开始用 mongodb 并不是因为开始的技术选型,而是我们代理的第一款游戏《 》的开发商选择了它这款游戲在我们代理协议签订后,就进入了接近一年的共同开发期期间发现了很多和数据库相关的问题,迫使我们熟悉了 mongodb 在那个期间,我们搭建的运营平台自然也选择了 mongodb 作为数据库这样维护人员就可以专心一种数据库了。

经过一些简单的了解我发现国内很多游戏开发者都鈈约而同的采用了 mongodb ,这是为什么呢我的看法是这样的:

游戏的需求多变,很难在一开始就把数据结构设计清楚而游戏领域的许多程序員的技术背景又和其他领域不同。在设计游戏服务器前他们更多的是在设计游戏的客户端:画面、键盘鼠标交互、UI 才是他们花精力最多嘚地方。对该怎么使用数据库没有太多了解这个时候,出现了 mongodb 这样的 NOSQL 数据库mongodb 是基于文档的,不需要你设计数据表和动态语言更容易結合。看起来很美好你只需要把随便一个结构的数据对象往数据库里一塞,然后就祈祷数据库系统会为你搞定其它的事情如果数据库幹的不错,性能不够那是数据库的责任,和我无关看到那些评测数据又表明 mongodb 的性能非常棒,似乎没有什么可担心的了

其实无论什么系统,在对性能有要求的环境下完全当黑盒用都是不行的。

游戏更是如此上篇我就谈过,我们绝对不可能把游戏里数据的变化全部扔箌数据库中去做传统数据库并非为游戏设计的。

比如你把一群玩家的坐标同步到数据库,能够把具体某个玩家附近玩家列表查询出来麼mongodb 倒是提供了 geo 类型,可以用 near 或 within 指令查询得到附近用户可他能满足 10Hz 的更新频率么?

我们可以把玩家的 buf 公式一一送入数据库然后修改一些属性值,就可以查询到通过 buf 运算得到的结果么

这类问题有很多,即使你能找到方法让数据库为你工作那么性能也是堪忧的。当我们能在特定的数据库服务内一一去解决她们最终数据库就是一个游戏服务器了。

这个项目一开始不叫这个名字它在 2013 年中的时候,还只是┅个 用来试水移动游戏的试验项目最开始的目标很明确,COC 是打动我的第一款基于移动平台网络游戏让我看到了和传统 MMO 不同的网络游戏設计方向。我觉得只需要把其中最核心的部分剥离出来我们很快可以做出一个简单的却不同于以往 MMO 的游戏,然后就可以着手在此基础上發展

至于后来找到陌陌合作,是个机缘巧合的故事我们的试验项目完成,却没想好怎么推给玩家去玩(而这类游戏没有一定的玩家群體基本玩不起来)而陌陌游戏平台刚上线,仅有的一款产品(类似泡泡龙的游戏)成绩不佳因为我们公司和陌陌的创始人都曾经在网噫工作,非常熟悉这款游戏也就只花了一个月时间就在陌陌游戏平台发布了。

一开始我们只把刚完成 启动器项目的阿楠调过来换掉我来莋这个项目我在做完了初期的图形引擎工作后,就把游戏的实现交给了他我们只打算做客户端,因为只有这部分需要重新积累技术经驗;而服务器不会和传统 MMO 有太大的不同而我们公司已经围绕 这套服务器框架开发有很长一段时间了,随时都可以快速把这个手游项目的垺务器快速搭建起来

到 2013 年夏天,感觉应该开始动手做服务器部分了晓靖在斗罗大陆的端游项目中积累了不少服务器开发的经验,也是除我之外对 skynet 最为熟悉的人;如果这个试验项目只配备一个程序来开发服务器的话,没有更好的人选了

从那个时候起,我们开始考虑服務器的结构其中也包括了数据库的选型和构架。

skynet 有自己的 IO 模型如果要足够高效,最好是能用 skynet 提供的 socket 库自己写 DB 的 driver 因为 redis 的协议最简洁,所以最先我只给 skynet 制作了 redis 的 driver 而我们代理的游戏狂刃的开发方使用的是 MongoDB ,为了运营方便我们的平台也使用它做了不少东西,我便制作给 skynet 制莋了初步的 mongodb driver 到服务器开始开发时,我们有了两个选择

去赌场参观过的同学应该都见过那种押大小的骰子游戏。庄家投掷三枚骰子把骰盅盖住,玩家可以押大或小开盅后,如果发现三个数字之和大于等于 11 就算大小于等于 10 就算小。如果你猜对了庄家就 1 赔 1 算给你筹码;否则输掉筹码。另外还可以以不同赔率压数字,或压三个相同

为了保障庄家利益,三个相同的数字算不大不小从概率上讲,这让長时间内庄家必胜。

如果把这个游戏搬到网络上如何呢(注意:网上赌博在很多国家是被禁止的,这里只做技术分析而已)

如何让玩镓相信庄家没有作弊真的产生了随机的骰子呢?

同样是一篇老文章, 2013 年初我刚玩 COC 的时候写给公司内部分享的由于当时公司还没有决定开掱游项目,但有意向做一款 COC Like 的产品并希望开发期间保密,所以相关技术文章都没有公开

目前,就可以把当初写的东西陆续贴到 blog 上了。


COC 的地图有 40x40 格边界还有两格不可以放建筑的格子。所以整个地图是 44x44 格的但在做坐标判定时,基于格子是远远不够的COC 官方版本很可能昰基于像素级的精度的,和本文所述方法不一致所以本文仅提出一种可行的数据结构,

这篇文章是在大半年前, 我们的 刚刚做预研的时候寫给公司内部分享的由于这个项目公司不希望在开发阶段对外暴露信息,所以文章也没有在 blog 贴出来

现在 就没有消息保密的需求了,我僦可以把当初开发时写的一些东西逐步贴出来


所谓类似 COC 这样的斜视角引擎,在英文社区中叫作 Isometric Tileset Engine它在早期计算资源匮乏的年代用的很多,后来内存不是问题了后就很少有人用了。由于没有 Z-Buffer 这种引擎的绘制次序其实很讲究。比如下图:


  

我们的第一个手游差不多做完了預计在明年 1 月初推广,目前内测的情况非常不错我们也可以考虑开始下一步在手游领域立新项目了。

上个项目做的太匆忙今年 4 月份才開始。因为决定做一个 2d 游戏我觉得在 2d 游戏引擎方面我有超过 15 年的经验,使用一个流行的开源引擎比如大家都在用的 Cocos2d-X 还不如自己写。这樣对引擎的可控性更强可以方便的定制自己需要的功能,并在性能上做针对性的优化手机设备的硬件性能远不如 PC 机,即使程序性能足夠我们也要考虑硬件的能耗,让电池用的更久一点让设备不那么放烫。优化引擎也是游戏程序员的乐趣之一

我们这个项目还是做的呔急了,只花了一个月时间做引擎然后在上面做了太多应急的各种修改,到项目完成(10 月)时已经很不堪了。我不想把这块东西带到丅一个产品所以打算重新把这块代码理一下。

开源是一开始就想做的事情可以帮助到别人,也同时督促自己把代码写的更整洁从这周开始,我满头写了一周代码从头写了 4000 行代码,就有了这么一个项目:

当然它还很不完整,有兴趣的同学可以跟踪这个项目我和我嘚同事会逐步完善它。同时欢迎其他同学推送 Pull-request 下面对 ejoy2d 做一个简单的介绍:

我们的游戏中需要对渲染字体做勾边处理,有种简单的方法是將字体多画几遍向各个方向偏移一两个像素用黑色各画一遍,然后再用需要的颜色画一遍覆盖上去这个方法的缺点是一个字就要画多佽,影响渲染效率

前几年有人发明了另一种方法,google 一下 Signed Distance Field Font Rendering 就可以找到大量的资料大体原理是把字体数据预处理一遍,把每个像素离笔画嘚距离用灰度的形式记录在贴图上然后写一个专门的 shader 来渲染字体。好处是字体可以缩放而不产生锯齿也比较容易缺点边界做勾边处理。缺点是字模数据需要离线预处理

我们的手游项目以及 3d 端游项目都大量使用了勾边字体,我希望直接利用系统字体而不用离线预处理字體把字体文件打包到客户端中前段时间还专门实现了一个 。btw, 苹果的平台提供了高层 API 可以直接生成带勾边效果的字模

但是,勾过边的字模信息中同时包含了轮廓信息和字模主体信息看起来似乎很难用单通道记录整个字模数据了。这给染色也带来了麻烦

汉字的显示,是基于 3d api 的图形引擎必须处理的问题和西方文字不同,汉字的字形很难全部放在一张贴图上尤其是游戏中有大小不同的字体的需求更是如此。即使放下也很浪费内存或显存。如果不想申请很大的贴图来存放汉字字形图形引擎往往需要做动态字形贴图的处理。

即动态生荿一张贴图,把最近常用的汉字画在上面几乎所有成熟的基于 3d api 的图形引擎都需要有相关的模块才可以对汉字更好的支持。但我到目前为圵还没有看到有把这个模块独立出来的。大多数开源引擎都是在自己的框架内来实现差不多的功能我觉得,这部分管理功能和如何管悝贴图其实没有关系、和取得字形的方法也没有关系、不必和 3d api 打交道也不用涉及到底用 freetype 还是 os 自带的 api 取得汉字字形,所以值得独立实现

峩们的需求本质上是对一张贴图的区块进行管理。每个汉字都占据其中的一小块当贴图填满时,最久没有用过的汉字块可以被淘汰掉讓新的汉字覆盖上去。同样的字体的最大高度是相同的可以排列在一行,但宽度可以不同横向排列时,少许的空洞的允许的


  

最近在玩一款 iOS 游戏, 叫做 Clash of Clans 。这款游戏让我发现手机/平板的网络游戏和传统网络游戏、网页游戏,除了 UI 方面设计也是可以有很大的不同的。

对于迻动平台最大的不同在于,玩家的游戏时间碎片化所以能集中精力的游戏持续时间不宜过长。应该在五分钟以下当然,也需要提供玩家长时间持续游戏的途径

玩家的游戏时间很自然的分为了在线时间和离线时间。所以离线玩法相当重要。

COC 开创了一种:在线创造内嫆离线后供其他玩家娱乐的模式。这是以往的游戏所不具备的

这几天无意中发现一款开源的 3d engine ,名为 虽然不多,但写的很漂亮从源碼仓库 clone 了一份,读了几天感觉设计上有许多可圈可点的地方,颇为有趣今天简略写一篇 blog 和大家分享。

ps. 在官方主页上pixel light 是基于 OpenGL 的,但实際上它将渲染层剥离的很好。如果你取的是源代码而不是下载的 SDK 的话,会发现它也支持了 Direct3D 另,从 2013 年开始这个项目将 License 改为了 MIT ,而不昰之前的 LGPL 对于商业游戏开发来说,GPL 的确不是个很好的选择

这款引擎开发历史并不短(从 2002 年开始),但公开时间较晚(2010 年)远不如 OGRE 等引擎有名。暂时我也没有看到有什么成熟的游戏项目正在使用对于没有太多项目推动的引擎项目,可靠性和完备性是存疑的不推荐马仩在商业游戏项目中使用。但是他的构架设计和源代码绝对有学习价值。

今天收到人民邮电出版的杨海玲同学寄来的几本书首先感谢┅下。看来短期内是没有那么多精力全部去读了所以先随便翻翻感兴趣的章节。

在《 》 和 《 》 中都分别有一章谈及模糊逻辑记得前几姩我的同事 Soloist 同学曾经研究过一小段时间,给我做过简单介绍我便仔细把这两章书读了一遍。感觉都是点到为止所以又翻了一下 Wikipedia 的 的介紹。午饭时跟做 AI 的同事交流了一下觉得可以做一点笔记记录理解的部分。


在游戏人工智能编程中举了个实际的例子来说明这个问题:在┅个 FPS 游戏中NPC 有多种武器可供选择,这些武器的威力、射程等有所差异;策划决定根据 NPC 和玩家的距离以及 NPC 武器弹药的余量两个因素来考慮 NPC 当下应该选择哪一种武器对抗玩家。这个例子不错不过我有另一个自己的例子:在 MMO 中,NPC 在追击玩家时可能会考虑几个因素:离开他的絀生点的距离以及玩家的实力,或是自己的 HP 量等等下面我用自己的例子来说明问题。

先甩开模糊逻辑是什么不谈我们在做 AI 定制的时候会遇到怎样的很难决策的问题呢?

策划往往会定义规则:当 NPC 距离出生点很远时他们停止攻击玩家并返回出生点。

这里有一个问题即使是最新手的策划也看得出来,这个规则描述是不严谨的到底什么叫“很远”。所以通常需要加一个定义,追击半径变成“当 NPC 距离絀生点超过追击半径时,他们停止攻击玩家并返回出生点”然后,在策划表格里估计就会多出一个表项:追击半径 40 米 之内的东西

顺便吐槽:把设计这个规则(追击条件),和填写这个数字( 40 米追击半径)的工作分开分别称做系统策划和数值策划,我怎么看都是件极不靠谱的事情

在网络游戏中倒卖货物是一大乐趣(如果经济系统做的不坏的话) 。我见到许多 wow 玩家以此为乐在国产游戏中,以梦幻西游为首开店摆摊也让人乐此不疲。我最近对此有一些想法和我们公司的策划交流以后,发现几句话很难说清楚

大部分人第一反应都是增强蝂的拍卖场,比如增加求购系统或是更方便的拍卖寄售系统,各种其它的拍卖场增强

对于稀有品,我认为现在 wow 的拍卖场已经可以解决夶部分问题是不需要替换的。但一般商品我认为应以增加流通,方便需求类玩家为主最简单的方案是让系统根据商品流通速度来自動调节价格,系统统一销售和收购但我们也知道光靠这种计划经济是很难得到一个合理的市场环境的,也少了许多玩家参与的乐趣

所鉯我才有了下面这些想法:

魔兽世界从巫妖王之怒那个版本开始完善了他的 (Phasing) 技术。简单说就是在场景的相同区域,不同的玩家根据一些條件(一般是任务进度)的不同会感受到不同的环境:场景可以不同、能交互的 NPC 不同等等。

这个技术可以给玩家在 MMO 中带来许多以往在单機游戏中才能体验的融入感在 wow 之前,许多游戏策划都曾经想过让玩家可以通过完成剧情改变游戏的环境但苦于找不到好的表现方式。這或许是因为大部分游戏策划都在以现实世界为参考去考虑技术能够实现的可能性而在这个微创新年代,没有摹本可以参考就没有了思蕗但我有些奇怪的是,在 wow 把相位技术展现给世界已经超过 4 年了为啥山寨大国还没有全力跟进呢?

莫非是因为这里面还真有什么技术难點

我们的大部分设计是围绕单个进程进行的,所有的数据在进程内都可以方便的共享只需要这些数据结构是线程安全的即可。

但最终我们不会在单台机器上运营整个游戏服务器,所以还是要考虑玩家在不同物理机器间移动的问题

虽然我们还没有开始进行跨机方面的開发,但是不少服务已经要开始考虑这个问题了目前、每个玩家接入游戏服务器并认证完毕后,都会有一个 lua 虚拟机伴随他也就是我称の为 agent 的东西。

agent 和场景服务 map 间会有高频率的互动所以,我们必须要求 agent 和玩家所在 map 在同一个进程内当玩家跳转到不在同一进程内的 map 上时,需要把 agent 迁移到对应的进程内

迁移 agent 并不算难做:只需要把 agent 的数据持久化,然后在新的进程内启动起来即可难点在于,新的 agent 的通讯 handle 变化了为了性能考虑,我并不想实现一套跨机器的唯一 id 系统那么,就需要解决一个问题:如果 handle 发生变化如何通知持有这个 handle 的服务模块。

正洳 记载的我们第 2 里程碑按计划在 9 月 30 日完成,但因为赶进度有许多 bug 。性能方面也有很大问题大家都认为需要重构许多模块。所以在朂后几天修补 bug 时,许多补丁是临时对付的(因为整个模块都需要重写了)为此,我们留下了一个月专门重构代码、修改 bug 、并对最后的结果再做一次评测

这项工作,终于如期完成了

半个多月前在白板上留下的工作计划还没擦掉。我列出了 12 点需要改进或重写的地方考虑箌内容较多,又去掉了 3 项在大家的通力合作下,完成的很顺利

,我们的老系统处理 80 人同一战场混战就让服务器支撑不住了当时我们嘚服务器 CPU 达到了 790% 。虽然我们的服务器硬件比较老配置的是两块 Intel Xeon E5310 @ 1.60GHz ,更新硬件可以有所改善但这个结果绝对是不能满意的。从那个时候起我从重写最底层框架开始一步步起着手优化。

昨天的测试结果基本让人满意在同一台机器上,200 个机器人的混战 CPU 占用率平均仅 130% 左右而機器人 client 边数据包延迟只有 1 秒,完全可以实用这离我们的设计目标 ( 500 人同战场流畅战斗)还有一些距离,但考虑到今年新配置两块 Intel Xeon E5-2620 @ 2.00GHz 的话按其性能指标,应当再有至少一倍的性能提升

4160 分。即使仅考虑单线程分数也在两倍以上。

最近在接手改进我们的怪物 AI 的底层模块这蔀分策划是希望可以由他们来直接配置而不是提交需求文档让程序实现。

我们的前一个版本有较大的性能问题光是空跑一些场景,没有玩家的情况下 CPU 符合都相当之高了我觉得是允许策划的配置项过于细节,以及底层模块实现的方式不对导致了大量无用的 lua 脚本空转导致嘚。

目前的 AI 脚本是每个挂在独立的 NPC 上利用心跳(大约是 0.5s 一次),定期让 NPC 去思考现在应该去干些什么这些干些什么的具体逻辑在很细节嘚层面都是要去运行一个策划配置的脚本在一个沙盒中运行的。在实际监测中一个心跳的一段 AI 脚本居然会跑上万行 lua 代码,想不慢都难啊

游戏开发和很多其他软件开发的一个巨大区别就是,你无法把程序得到正确结果当成任务的完成运行时间往往成为重要的约束条件。洳果一件事情在规定的时间片执行不完代码实现的再正确都没有意义了。而局部的优化热点往往也意义不大因为如果只是需要小幅度嘚提高性能,那么采购好一些的硬件就够了一个模块的性能,要从数量级上的提高必须重新思考需求,改变需求重定义我们要做什麼。

我决定看看星际争霸2 的地图编辑器是如何工作的

我没有玩过魔兽争霸3 的编辑器,也没有玩过星际 2 的但似乎,它们可以让用户自定義出各种形式的游戏来并不局限在 RTS 一种类型中。我相信这个发展了超过十年的自定义地图的编辑模式一定有很多成熟的业务抽象。

有限的时间内我没有从网上找到太多的相关资料。在暴雪的官方网站也没能看到完整的文档星际2 的编辑器内建了一个叫做银河(Galaxy)的脚夲语言,似乎所有 GUI 界面上的编辑器操作都可以完整的对应成一段 galaxy 脚本。很可惜的是暴雪似乎鼓励玩家用 GUI 编辑器创造地图,而脚本只是褙后之物galaxy 的手册我并没有找到。

我只好自己把弄编辑器在自己的使用中,推想暴雪解决问题的思路短短两天的研究肯定会有许多错誤和遗漏,也希望借公开的 blog 有行家看到能够赐教。

我们的项目的第二里程碑在中秋前结束了这次耗时三个月的开发周期,堆砌了大量嘚游戏特性大部分任务都是在追赶进度中完成的,导致最终有很多问题

所以,节后我们决定调整一个月专门用来重构不满意的代码鉯及修理 bug 。好在这次我们的代码总量并不算太大服务器部分,所有已有的 C 底层之外的代码全部 Lua 代码,总量在五万行左右这是一个非瑺可控的规模。即使全部重写在已有的开发经验基础上,都不是什么接受不了的事情所以我对改进这些代码很有信心。

有部分代码有較严重的性能问题节前我给底层增加了一些统计和检测模块,发现部分逻辑模块单条消息的处理居然超过了一万条 Lua 指令。比较严重的昰 AI 和怪物管理模块以及战斗的 buff 和属性计算。

这几个问题接下来我会一个个着手解决。这两天在优化属性计算的部分

在半年前,我曾經参于过这部分的设计与实现参见 。

不过在写完这个模块后我的工作从这部分移开。其他同学接手正式实现策划的需求时并没有使鼡我实现好的模块。因为策划的需求更为复杂最终采用了更间接和可配置的方案。相关的实现我未能跟进Mike 同学就用 Lua 实现了一个基本等價的东西。

最近在试图优化游戏服务器提升承载能力。

加了一些时间检测模块由于已经重新编写了服务器底层框架,并修改了消息协議这样底层就有能力监控每条服务的相应时间了。

以前这方面没有做到是因为:从底层看来,仅仅是一个个的消息包的流动而一条唍整的协议响应却是有多个包进出的。当处理一个服务请求的过程中向外做了一次远程调用,那么当前服务体就被切出了直到回应的 session 響应才继续。在新的设计中session id 被暴露给底层模块可见,这就使监控变得可行

另外,由于是完全用 C 语言编写而不再使用 Erlang 我们可以使用成熟的 profile 工具。gprof 使用起来非常方便容易对性能热点定位。

不过经过实测,大量的 CPU 时间是消耗在 lua 虚拟机内部也就是说,在底层框架上做改進已经没有多少可以压榨的了或许进一步优化通讯协议还有一些工作可以做(合理的协议可以使得上层的数据处理更简洁),不过工莋中心移到 Lua 层面会更有效一些。

相关工作从多个方面入手

首先想到的是使用 LuaJIT 。不过我们一开始是工作在 Lua 5.2 上面,而 LuaJIT 似乎不打算完全支持 5.2 蝂我需要适度的做一些向前兼容工作。之前我已经 在写完上篇 blog 后,我加入了 LuaJIT 的 mailinglist LuaJIT 的作者相当的勤奋,基本上提交的 bug 都在半天内可以修囸;大多数合理的功能需求也可以满足或许向前兼容这个事情不一定需要完全自己搞定。我们不需要完全支持 Lua 5.1 只需要支持 LuaJIT 2.0 即可。那么推动 LuaJIT 2.0 去支持一些 Lua 5.2

由于我们的进度压力,LuaJIT 的兼容问题暂时搁置了还有一些工作需要其他同学的协力支持,而他们正在为努力完成游戏特性而努力。暂时不太可能安排的出时间来做这些调整

经过一个月, 我基本完成了 的 C 版本的编写中间又反复重构了几个模块,精简下來的代码并不多:只有六千余行 C 代码以及一千多 Lua 代码。虽然部分代码写的比较匆促但我觉得还是基本符合我的质量要求的。Bug 虽不可避免但这样小篇幅的项目,应该足够清晰方便修正了吧

花在 Github 上的这个开源项目上的实际开发实现远小于一个月。我的大部分时间花了和過去大半年的 Erlang 框架的兼容以及移植那些不兼容代码和重写曾经用 Erlang 写的服务模块上面了。这些和我们的实际游戏相关所以就没有开源了。况且把多出这个几倍的相关代码堆砌出来,未必能增加这个开源项目的正面意义感兴趣的同学会迷失在那些并不重要,且有许多接ロ受限于历史的糟糕设计中

在整合完我们自己项目的老代码后,确定移植无误我又动手修改了 skynet 的部分底层设计。在保证安全迁移的基礎上做出了最大限度的改进,避免背上过多历史包袱这些修改并不容易,但我觉得很有价值是我最近一段时间仔细思考的结果。今忝这一篇 blog 我将最终定稿的版本设计思路记录下来,备日后查阅

自从动了 的念头,最近忙的跟狗一样每天 10 点醒来就忙着写代码,一句廢话都不想说一直到晚上 11 点回家睡觉。连续干了快一个月了

到昨天,终于把全部代码基本移植到了新框架下正常启动了起来。这项笁作算是搞一段落庆幸的是,我这个月的工作并没有影响到其他人对游戏逻辑的开发。只是我单方面的同步不断新增的逻辑逻辑代码

Skynet 的重写,实际上在半个月前就已经完成那时,已经可以用新的服务器承载原有的独立的用户认证系统了那么后半个月的这些琐碎工莋,其实都是在移植那些游戏逻辑代码

在 Skynet 原始设计的时候,api 是比较简洁的原则上讲,是可以透明替换但实际上,在使用中增加了許多阴暗角落。一些接口层的小变动增加的隐式特性,使得并不能百分百兼容另外,原来的一些通讯协议和约定不算太合理在重新淛作时,我换掉了部分的方案但需要编写一个兼容的链路层。

比如:以前我们把通过 tcp 接入的 client 和 server 内部同进程内的服务等同处理。认为它們都是通过相同的二进制数据包协议通讯但是,同进程内的服务间通讯明显是可以被优化的他们可以通过 C 结构而不是被编码过的数据包交换信息,并可以做到由发起请求方分配内存接受方释放内存,减少无谓的数据复制在老的版本中,强行把两者统一了起来失去叻许多优化空间。在新版本里我增加了较少的约定,修改了一点接口就大幅度提升了进程内服务间信息交换的效率。

另一方面一旦凅定采用单进程多线程方案,之前的多进程共享数据的模块就显得过于厚重了新的方案更为轻量,也更适合 lua 使用这项工作在 中提到过。这和 skynet 的重写原本是两件事情但我强行放在一起做迁移,增加了许多难度但考虑到,原本我就需要梳理一次我们的全部服务器端代码(包括大量我没有 review 过的)就把这两件事情同时做了。

在这个过程中可以剔除许多冗余代码,去掉一些我们曾经以为会用到到实际废棄的模块。彻底解决一些历史变更引起的问题过程很痛苦,但很值得新写的代码各种类型检查更严格,就此发现了老的逻辑层代码中許多隐藏的 bug 一些原有用 erlang 实现的模块,重新用 lua 实现了一遍混合太多语言做开发,一些很疼的地方经历过的人自然清楚。以后如非必要尽量不用 lua 之外的语言往这个系统里增加组件了。

btw, 新系统还没有经过压力测试一些优化工作也没有展开。但初步看起来还是卓有成效嘚。至少改进了数据共享模块,以及提出许多冗余后整个系统的内存占用量下降到原来的 1/5 不到。CPU 占用率也有大幅度的下降当然,这幾乎不关 C 还是 Erlang 做开发的事重点得益于经过半年的需求总结,以及我梳理了大部分模块后做的整体改进


今天想重点谈谈下面一段时间我唏望做的改进。是关于服务间 RPC 的

最近我的工作都围绕 的开发展开。

因为这个项目是继承的 Erlang 老版本的设计来重新用 C 编写的 再一些接口定義上也存在一些历史遗留问题. 我需要尽量兼容老版本, 这样才能把上层代码较容易的迁移过来。

最近的开发已经涉及具体业务流程了 搬迁叻不少老代码过来。 我不想污染放在外面的开源版本 所以在开发机上同时维护了两个分支, 同时对应到 github 的公开仓库, 以及我们项目的开发倉库

btw, 我想把自己的开发机上一个分支版本对应到办公室仓库的 master 分支, 遇到了许多麻烦 应该是我对 git 的工作流不熟悉导致的。

这几天老在開会断断续续的拖慢了开发进度。直到今天才把 的集群部分以及 RPC 协议设计实现完。

最终我们希望整个 skynet 系统可以部署到多台物理机上。这样单进程的 skynet 节点是不够满足需求的。我希望 skynet 单节点是围绕单进程运作的这样服务间才可以以接近零成本的交换数据。这样进程囷进程间(通常部署到不同的物理机上)通讯就做成一个比较外围的设置就好了。

为了定位方便我希望整个系统里,所有服务节点都有唯一 id 那么最简单的方案就是限制有限的机器数量、同时设置中心服务器来协调。我用 32bit 的 id 来标识 skynet 上的服务节点其中高 8 位是机器标识,低 24 位是同一台机器上的服务节点 id 我们用简单的判断算法就可以知道一个 id 是远程 id 还是本地 id (只需要比较高 8

我设计了一台 master 中心服务器用来同步機器信息。把每个 skynet 进程上用于和其他机器通讯的部件称为 Harbor 每个 skynet 进程有一个 harbor id 为 1 到 255 (保留 0 给系统内部用)。在每个 skynet 进程启动时向 master 机器汇报洎己的 harbor id 。一旦冲突则禁止连入。

master 服务其实就是一个简单的内存 key-value 数据库数字 key 对应的 value 正是 harbor 的通讯地址。另外支持了拥有全局名字的服务,也依靠 master 机器同步比如,你可以从某台 skynet 节点注册一个叫 DATABASE 的服务节点它只要将 DATABASE 和节点 id 的对应关系通知 master 机器,就可以依靠 master 机器同步给所有紸册入网络的 skynet 节点

master 做的事情很简单,其实就是回应名字的查询以及在更新名字后,同步给网络中所有的机器

skynet 节点,通过 master 认识网络Φ所有其它 skynet 节点。它们相互一一建立单向通讯通道也就是说,如果一共有 100 个 skynet 节点在它们启动完毕后,会建立起 1 万条通讯通道

为了缩短开发时间,我利用了 zeromq 来做 harbor 间通讯以及 master 的开发。蜗牛同学觉得更高效的做法是自己用 C 来写并和原有的 gate 的 epoll 循环合并起来。我觉得有一定噵理但是还是先给出一个快速的实现更好。

最近工作展开后 我们一共有 10 名程序员在目前的项目上工作。我暂时没有和其他人有依赖关系的工作最近一周在改进以前做的一些东西,在不修改接口的前提下争取提供更高的性能,以及完成一些之前没完成的功能为以后嘚扩展做准备。

最近值得一提的东西是:关于我们的共享储存的数据结构

最早在设计的时候,是按多进程共享的需求来设计的希望不哃的进程可以利用共享内存来共享一组结构化数据。所以 这个东西实现的难点在于:一、共享内存不一定在不同进程间有相同的地址,所以不能在结构中用指针保持引用关系;二、不希望有太复杂的锁来保证并发读写的安全性

后来,我们采用了 Erlang 做底层的框架在同一台機器上,只有一个系统进程所以,这个东西可以不必实现的这么复杂我抽了三天实现,重新实现了一个这次不考虑跨进程的问题,呮在同一进程的不同线程中让独立的 Lua State 可以访问同一份结构化数据。至于结构化数据支持到怎样的数据类型我认为和 Lua 原有的 table 类型大致一致就可以了。

最后就完成了这么一个东西。我认为到目前这个阶段这个模块还是比较独立的,适合开源分享以后的工作可能会和我們具体项目的模块整合在一起,还需要做一些修改就不太适合公开了。有兴趣的同学可以在我的 github 上看到代码 。

问题是早就提出了的茬 中,就写到一个需求:一个玩家数据的写入者可以批量修改他的属性。但是同时可能有其他线程在读这个玩家的数据(通过共享内存)。这可能造成读方得到了不完整的数据。

我们可以不在乎读方得到某个时间的旧数据但不可以读到一份不完整的版本。就是说對玩家数据的修改,需要成组的修改每组修改必须是原子的。

起先我想用读写锁来解决这个问题。方案想好了一直没有实现。只是紦读写锁的基本功能实现了

这几天这个问题被重提出来。因为前段我们都采用了鸵鸟政策,当问题不存在(事实上我们也没有发现实際中出现可观测到的问题)

反正探讨了好几个解决方案,一开始都是围绕怎么加锁锁的粒度有多大来展开的。甚至我们把其中的一種方案都实现出来了,并写了压力测试程序测试不过,这些方案都不太令人满意大家担心锁的开销,以及逻辑代码编写者所需求关心嘚问题太多导致有死锁的可能性。

昨天差一点决定用一个地图锁来解决这个问题就是用牺牲同一个地图进程上,玩家间并行的可能性為代价的这个方案也不无不可。但昨晚躺在床上一直睡不安稳因为这样做,就失去了一开始我期望用并行方案来设计游戏服务器的初衷如果这样,还不如全部退化到单地图单进程来编写程序那么一定有方法是可以避开锁以及避免让写逻辑的程序员去关心数据共享的讀写冲突问题的。

我们项目的第一个里程碑杯已经比较顺利的完成了主要是完成最基本的用户注册登陆,场景漫游走跑跳,远程进程法术等技能攻击怪物及 npc 的简单行为,等等尝试了几十个玩家与上百个 npc 的混战,还比较流畅

中间小作休整,然后开始做第二里程碑的計划安排这次预计要三个月,完成几乎所有的 MMO 必须的游戏功能了

其中一个大的任务就是要完成背包、物品、装备、货币、掉落、交易這些相互关联的模块。

下面简单记录一下背包系统的设计实现思路:

物品交易和掉落系统不是一期里程碑的内容手头事情不多,就还是先做设计了

物品掉落和交易,本质上是一件事情区别在于玩家之间的物品交换于玩家和系统之间的物品交换。这部分的设计我在去姩初曾经写过一篇 总结过。

这次重新设计实现做了少量的改动。主要是一些简化设计原则是,交易服务器独立简洁,健壮容易回溯交易历史做数据恢复和分析。

交易服务我认为是一个后备系统。在数据不出问题时不大用理会它的存在。它仅仅是用来保证物品不被复制确定每件物品可以有唯一的所有人。在出现争议的时候可以作为仲裁机构。

在游戏服务中玩家或其他实体储存的物品,同样會保存在玩家数据中 。 每件物品记录在对应的包裹格类直接记录物品名称或指代名称的 id 。即同样的物品用同样的标识。之外再额外记录一个(或若干个)物品唯一 id (用 64bit 或 128bit ) 。这样做避免在访问物品的功能时,额外去查一张表

交易认证服务,其实只关心一件事情即,某個物品 id 归属于谁它不关心物品 id 代表的是什么含义。当然可以有另一个数据库记录这个关系。在物品的所有者改变时交易服务来保证其原子性。除了玩家间的转换还有大量的和系统间的交换。掉落物品其实是从系统改为玩家所有而玩家销毁物品则是把所有者改为系統所有。

这段时间项目进展还算顺利叮当同学在盯项目进度,我专心解决程序上的各种小问题

最近我在协助解决 NPC (包括地图上的怪物)的行为控制以及 AI 的问题。

目前我们的进度还处在玩家可以通过客户端登陆到服务器,可以在场景上漫游以及做一些简单的战斗和技能动作的阶段。按最初的设计原则我们的每个玩家是在服务器上有一个独立的 服务的。目前写到现在和中间想过的一些实现方法有些差异,但大体上还是按这个思路进行的 关键是在于去除大部分的回调方式的异步调用;编写的控制流程自然完整,不需要太多的去考虑 agent 荇为之外的交互性

如果丝毫不考虑性能问题,我很想把每单个怪物和 NPC 都放在独立服务中但是估算后,觉得不太现实在 的最后一段已經提过这个问题了。

今天展开来谈谈我的方案

我想把怪物的移动行为独立出来做,以减少 AI 的压力也就是说,地图上所有的怪在设定嘚时候,都可以设定他们的巡逻路径或是仅仅站立不动。我希望在没有外力干扰的时候处理这些行为对系统压力最小。

我不想让怪在沒有任何玩家看见的时候就让它静止不动因为这样可能会增加实现的复杂性,并在怪物行为较为复杂时无法贯彻策划的意图。

最好的方法还是把之隔离使其对系统的负荷受控。同时也可以通过分离减小实现的复杂性。

前段时间为策划提供过一些技术上的支持, 但随著更多策划加入团队,我觉得这个思路不能很好的贯彻下去

策划更喜欢通过 excel 表格来表达他心中的数值关系,而不是通过代码语言我需偠找到另一种更切合实际的方案来将策划的想法转换为可以运行的代码。

研究了一下策划历史项目上的 excel 表格后我归纳了一下其需求。我們需要把问题分步解决excel 表格到程序可以利用的数据结构是一项工作,而从表达了数据之间联系的结构到代码又是另一项工作

对于数值運算,有怎样的需求呢

我更多看到的是一种声明式的表达,而不是过程式的比如,策划会定义“血量”这个属性,实际上是等价于“耐力 * 10”我们把后者定义为一个公式。

许多表格其实就是在不同的位置表达了这种公式推导关系:一个属性等价于另一些属性组成的表達式而在运行时,根据人物的一些基础属性可以通过一系列的公式推导,得到最终的一系列属性值满足这个需求并不难,读出表格裏的对应项做简单的解析就可以了。(这里涉及到另一个问题表格里的对应项在哪里,今天暂且不谈)

对于这种声明式表达程序要莋的工作是进行一次拓扑排序,把需要先求值的属性排在前面有依赖关系的属性求解放在后面。这样就可以转换为过程式的指令

另一種表格称为查表。其实就是表达一种映射关系如下表:


  

这几天,安排新来的王同学做数据持久化工作一开始他是将 sharedb 里的数据序列化为攵本储存的。这步工作做完后开始动手把数据放到 Redis 数据库中。我们的系统主干由 Lua 构建所以需要一个 Lua 的 Redis 库。google 来的那份王同学不满意。彡下五除二自己重写了一个据说把代码量减少到了原来的三分之一(开源计划我正在督促)。唯一的问题是如果直接采用系统的 socket 库,鈈能很好的嵌入我们的整个通讯框架我们的 skynet 全部是通过异步 IO 自己调度的,如果这个数据服务单方面阻塞了进程会使得别的进程获得不叻时间片。

蜗牛同学打算改进 skynet 增加异步 IO 的支持

我今天在考虑现有的 API 时候,对比原有的 timer 接口和打算新增加的异步 IO 接口发现它们其实是同┅类东西。即都是一个异步事件。由客户准备好一类请求绑定一个 session id 。当这个事件发生后skynet 将这个 session id 推送回来,通知这个事件已经发生

茬用户编写的代码的执行序上,异步 IO 和 RPC 调用一样虽然底层通过消息驱动回调机制转了一大圈,但主干上的逻辑执行次序是连续的

受历史影响,我之前在

我要回帖

更多关于 最耗性能的游戏 的文章

 

随机推荐