October 10, 2019

三国志战略版服务器卡顿问题

我们的新作品 三国志战略版 上线有一小段时间了。市场反应不错,获得了许多玩家。随着玩家数量增加,服务器也产生了严重的卡顿问题,在每天高峰期尤其严重。

这个产品的服务器开发团队在立项之初并没有接触过 skynet ,可以说是从头学习起,在很短的时间内就完成了项目,还是很不错的。我没有参加过这个项目的开发,在问题显露的那几天正巧国庆假期在国外度假,远程参与了一些讨论。帮助分析了问题,等休假完毕后,昨天又开了一整天的会,大致了解了游戏的玩法(需求),结合前两天的思考,给了几套不同的改进方案。

阅读全文 "三国志战略版服务器卡顿问题" »

September 23, 2019

群星的经济系统

群星是个非常复杂的战略游戏。我玩了 3 年多,600 多小时。这三年一直在跟进中文化工作,校对及翻译了几十万字的文本,可以说是非常喜爱了。

如果有机会,我希望日后可以制作一款类似的战略游戏。我认为我应该把群星的系统好好整理成文字,这样帮助自己看出它的设计思路。群星采用了一种独特的商业模式,就是不断地积累忠实玩家,然后按周期推出收费的新玩法,让玩家持续付费。不用于常规的售卖游戏内容,它是在售卖游戏玩法。现在的版本和 3 年前推出的版本,可以说是在玩法上有天翻地覆的变化。

这样,玩家其实在花钱购买新的体验,而创作者则一步步的完善游戏系统,不用太担心一下次引入过多的系统导致玩家学习曲线过高,也不用担心有设计失误:总可以在下个版本修改。而玩家也比较放心,只要持续付费,跟着设计者的脚步走,总有新奇的享受,还免去了玩新游戏从头学习的成本。

群星的整个系统太复杂了,远非一两篇 blog 所能写清楚的。我想先记录一下 2.3 版本的经济系统,是俗称“种田”玩法中的重要部分。其实,群星有个官方的 wiki ,讲解的非常清楚 。我只是根据自己玩游戏过程的理解,重新整理一下而已。

我玩过的最早的战略游戏当属三国志系列,一开始就有所谓的内政系统。但是它仅仅只是简单的用武将提升一下城市的繁荣度的数字而已。虽然已经有人口、金钱、粮草的不同维度,但相互影响非常简单。数值发展的空间也只跟招募到的将领能力和原本设定好的城市基础值有关系。内政系统不太可能成为独立的游戏乐趣来源。

而从文明系列开始,经济发展就变得错综复杂,过于简单的经济设定已经无法满足战略游戏的设计需求了。这类战略游戏的玩家不满足于一个指令下去,某个维度的数值就提升起来,这种简单直白的系统。不同维度的数值间相互制约,玩家根据每局游戏随机出来的环境、对手,动态的调整策略,在多种制约下找到最高效率的发展路径,成了游戏重要的乐趣来源。

群星和文明不同,它没有采用分时回合制,而采用了即时带暂停的模式。但本质上还是一种同步回合制。所有玩家/非玩家都是同时进行行动的,主动指挥的单位行动以天(游戏中最小的时间单位)为回合推演,而行动对经济系统的影响则以月为周期结算。我认为两种模式各有优劣,但我更喜欢即时带暂停的模式,它也更适合在网络上对战。

阅读全文 "群星的经济系统" »

September 16, 2019

场景层次结构的管理

今年上半年的时候,就想把我们游戏引擎中场景层次结构管理模块的设计记录一下。每次想写的时候都在做小调整。直到最近,算法和数据结构才稳定下来。今天做一个记录。

游戏里的场景对象,通常以树结构保存。这是因为,每个对象的空间状态,通常都受上一级的某个对象影响。

从管理角度讲,每个对象最好都能知道它可以影响其它哪些对象;且必须知道它被哪个对象影响。所以,这会用到一个典型的树结构。尤其在做编辑器时,树结构还会直接呈现在编辑界面上。不过,我认为在运行时,从父对象遍历到子对象的需求并不是必要的,需要时可以额外记录。从数据上考虑,父亲记住孩子和孩子记住父亲,是重复了同一种关系信息。如果不需要记住孩子的兄弟次序,那么在核心数据结构中,我们只需要让孩子记住父亲就足够了。

去掉冗余信息可以简化数据结构、减少维护成本、避免犯错误。尤其对于 ECS 架构,我希望所有对象都是平坦的,在场景对象组件上,一个 parent id 可以最少的构造出场景的层次结构出来。

阅读全文 "场景层次结构的管理" »

August 23, 2019

让 lua 运行时动态切换操作系统线程

最近我们在开发引擎时遇到一个和操作系统有关的问题,想了个巧妙地方法解决。我感觉挺有意思,值得记录一下。

在 ios 上,如果你的程序没能及时处理系统发过来的消息(比如触摸消息等),系统有机会判定你的程序出了问题,可能主动把进程杀掉。

完全自己编写的应用程序,固然可以把处理消息循环放在最高优先级。即使有大量耗时操作,也可以通过合理的安排代码,不让消息处理延后。但作为引擎,很难阻止使用者阻塞住主线程做一些耗时的操作。所以,通常我们会把窗口消息循环和业务逻辑分离,放到两个不同的线程中。这样,消息处理线程总能及时的处理系统消息。

在 windows 上,允许程序在任何一个线程做窗口消息循环。但在 ios (以及 Mac)上似乎不行。窗口消息循环必须在主线程中运行。

阅读全文 "让 lua 运行时动态切换操作系统线程" »

August 16, 2019

游戏引擎中的资源生命期管理问题

最近我们开发中的游戏引擎在修理资源管理模块中的 bug 时,我提出了一些想法,希望可以简化资源对象的生命期管理。

其实这个模块已经被重构过几次了。我想理一下它的发展轨迹。

最开始,我们不想太考虑资源的生命期问题,全部都不释放。当然,谁都明白,这种策略只适合做 demo ,不可能用在产品中。

因为我们整个引擎的框架是用 lua 搭建,那么,最直接的想法就是利用 lua 自带的 gc 来回收那些不被引用的资源对象。我不太喜欢这个简单粗暴的方法。因为首先, gc 不会太及时,其次 gc 方法触发的时机很难控制,容易干扰正常的运行流程。图形显示模块是时间敏感的,如果因为资源释放占用了 cpu 的话,很容易变成肉眼可查的卡顿。

另一个促使我们认真考虑资源管理模块的设计的原因是,当我们从 demo 过渡到现实世界的大游戏场景时,过多的资源量触发了 bgfx 的一个内部限制:如果你在一个渲染帧内调用了过多资源 api (例如创建新的 buffer texture 等),会超出 bgfx 的多线程渲染内部的一个消息管道上限,直接让程序崩溃。

所以我们不得不比计划提前实现资源的异步加载模块,它属于资源管理模块的一部分,所以也就顺理成章的考虑整个资源管理模块的设计。

阅读全文 "游戏引擎中的资源生命期管理问题" »

August 02, 2019

资源文件的转换问题

我们上周在游戏引擎上面的工作中遇到一些 bug ,涉及到过去的一些设计问题。维持讨论了几天解决该问题的方案。今天终于把最终方案确定了下来,值得做一个记录。

bug 出在游戏资源文件的转换上面。

游戏里用到的资源通常需要一个导入资源库的过程,例如你的原始贴图是一个 png 文件,但是引擎需要的是对应运行平台的压缩格式,windows 上是 dxt ,手机上是 ktx 等等。这个过程,在 Unity 等商业引擎中,是放在资源导入流程中。

我们的引擎把这个转换过程放在虚拟文件系统这个层次。这个设计决策是因为,我感觉统一导入资源是个痛点,用的人通常需要等待导入过程。Unity 用了 cache server 来解决这个痛点,但我认为 cache server 也存在一些设计问题 ,这个会在后面再展开一次。

我更希望转换过程是惰性的,直到最终运行需要的资源才需要转换。

阅读全文 "资源文件的转换问题" »

July 24, 2019

程序员应该怎样提高自己

经常有小(我 20 岁左右的)朋友问我,作为一个程序员该怎样提高自己。每个人的经历不同,所处环境不错,其实这个问题很难具体回答。不如好好写一篇总结,以后就不必每封 email 都重新写一次了。

纵观我近 30 年的编程生涯,在每个时期,我看到的东西都不同。想必再过 10 年还会有变迁。我只能写写当下眼界所及之处。

阅读全文 "程序员应该怎样提高自己" »

Misc

Categories

Archives

Recent Comments