« March 2023 | Main | May 2023 »

April 17, 2023

今年玩的一些游戏

我们正在开发一款类似 Factorio 的游戏 ,以修建自动化工厂为主要玩点。其游戏背景接近火星殖民。所以,最近一年我玩了相当数量有类似点的游戏,希望能得到一些启发。

其中有三款以火星殖民为主题的新游戏我个人很喜欢,值得推荐一下:

其一是 Farlanders ,像素化的画风很复古,很对我的胃口。游戏是回合制的,节奏很快。从中可以找到许多桌游的元素。紧凑的四边形格子地图,地形改造,隧道、电线、水管,这些都需要玩家精心布局。

如果玩自由模式的话,后期会偏简单,有点无趣。但是它的故事模式的难度调的相当好。如果选困难(我觉得开发者是围绕这个难度制作的),到了第 6 关就很难一次过关了。

btw, 我在这个游戏中还学到了一个交互设计上的防呆处理手法。

菜单有一个按钮是不希望玩家误碰的(因为可能会删除档案),一般的做法是按了之后再弹出一个模式对话框二次确认;也有人做成这种按钮需要长按一段时间才能确认。

而这个游戏的做法是按了这个按钮后,在按钮的右侧再出现一个新的按钮,上面有画有一个勾勾。玩家需要移动鼠标去点击这个新的勾勾按钮才真的执行该操作。没有其它额外的说明文字。这个防呆设计让我觉得很舒服,而且非常适合在手机上实现。

第二个游戏是 Plan B: Terraform 。这个游戏目前的内容少了点,给人有点虎头蛇尾的感觉。我玩的第一感觉是那个无人机平台的物流设计有些惊艳。这启发了我,我们正在开发的游戏立刻做了很多类似的设计。

但是、它的公路和铁路物流就过于简单了。公路网和铁路网都没有任何交通问题,不同路线的车辆可以穿插,同一路线的车辆只是做了简单的队列。玩到后期几乎没有什么安排路网的策略,直接拉线就行了。我们在做的游戏复杂的多,玩家是要考虑堵车问题的。

最后的地球化改造做的太粗糙了,希望以后能完善。

第三个游戏是 Terraformers 。这个更桌游化一些。我玩得很上头,几乎所有模式都在最高难度通关了。这个款游戏的味道是在最高一档难度下品出来的。最后十几个回合几乎都是压着好感度完成的,稍微一个错误的决策就会崩盘。在低难度下,地球化改造根本不重要,从各种途径拿分快速完成目标就行了。只有高难度下,快速膨胀的好感度需求,才会逼迫玩家精确计算该怎样才能跟上节奏。

另外还有三款稍微老一点,我在前两年玩过的。

一个是 Per Aspera ,游戏比较强调公路网的效率。但它的公路这块过于简化了。路网都是自动生成的,运输车也不需要干预,玩家在物流方面可以做的事情比较少。而其它方面繁琐的操作又比较多。后期加了一些战斗元素,有点画蛇添足吧。或许开发者觉得如果去掉战斗部分,剩下的部分内容不够支撑整个游戏吧。我前后玩了十多个小时,没能通关。

另一个就是前些年 Paradox 发行的 Surviving Mars 。按 P 社的调性,目前的版本应该完善了许多吧。我当初在刚发行的时候玩了十多个小时,感觉是个半成品,就没玩下去了。

还有一个 Infreaspace 。第一眼看到的时候感觉和我们想做的游戏非常接近。实际玩下来感觉物流系统太粗糙了。里面的汽车运输轨迹是假的,车不会跑回程,还可以突然从马路上变出来。建筑的布局也仅仅需要考虑相关建筑挨在一起有产能加成。所以不是很推荐。


今年我另外还玩了另外一些和城市建设、有物流元素的游戏。有些是新出的、有些是补课老游戏。

最喜欢的一个是 Against the Storm 。这个游戏把一局动辄十个小时起的城市建设游戏压缩到一个小时左右,这样玩的时候心理负担不会太大。这局没玩好,就再来一盘好了。而且它里面的建筑大多可以自由移动(有些免费,有些需要支付一点成本),减少了很多布局的压力。Factorio 也可以无成本的改变布局,但不如这个方便。

我在我们的游戏中也加入了免费移动建筑的设定。我相信这类游戏的玩家都会喜欢这一点。

另外一个是 Timberborn ,以海狸修水坝为题材的。我认为其出色点在于立体的地图设计。地图是人为设计出来的,目前看起来不适合做随机生成。正式因为认为设计,所以上手后最关键的玩点就是判断应该怎样依托地形去布局。

海狸里面的两个设计点在我看来比较有趣。一个是族群的设定,即使在这么小的地图上,也可能需要划分出多个族群,每个族群在物流上是相对独立的。另一个是能量传输需要靠建筑贴在一起(而不是传统的电线杆覆盖一定范围),而这些贴靠是在 3D 空间进行,有三个维度可以扩展,这对城市建设类游戏来说,拓展了相当的深度。相比较而言,戴森球那种同种建筑叠罗汉的设计本质上还是在平面上建设。

Dwarf fortress 是这类游戏的鼻祖,过去我一直都没有好好玩。去年底它出了 steam 版本,加入了新的图形界面,我就好好尝试了一下。在此之前,我有了很多 Rimworld 的游戏经验,玩起来上手很快。不过现在没有中文翻译,玩的时候有许多生词需要查字典。如果向人推荐游戏的话,我更倾向于 rimworld 。

比 rimworld 轻量一点的是 Prison Architect 。画风很相像,我一度认为是同一个作者制作的。但玩起来感觉颇为不同。prison architect 更偏建筑和规划,rimworld 则能感受到大量的程序化生成的故事,甚至会和 npc 共情。按 rimworld 作者自己的说法,他就是想做一个故事生成器,npc 建设基地的玩法只是一个载体罢了。

最后一个值得推荐的是 Oxygen not included 。我最后一次玩它是在 2021 年了,这里提几句只是因为和上面提到的游戏属于同类。而这么优秀的游戏若不列在同一篇文章中,有点说不过去。缺氧在我看来是能够和 Factorio 相提并论的游戏。甚至它们的最终目标都是发火箭。而缺氧最值得一提的玩法是气体的处理,不同的气体可以混合在同一个地图单元中,遵循热力学的规则运动,这是 Factorio 中没有的。从某些角度看,缺氧的机制要更为复杂。不过更复杂的规则更容易滋生 bug ,在我玩的时候,还是存在一些类似无限压力舱室可以保存无限气体/液体的 bug ,不知道现在修正了没有。

April 12, 2023

SQL Server 向 MySQL 的迁移方案

昨天做内部晋升评审时听到候选人介绍他即将开始的一个项目。大致是我们公司从韩国买过来一个游戏(有全部源码)打算自己运营。该游戏服务器全部用 C++ 编写,使用 SQL Server 做数据库。我们这个项目,除了需要根据市场做二次开发外,还希望把 SQL Server 迁移到 MySQL 上。成本是最主要的原因,如果可以迁移成功,成本将减半甚至更多。该成本差异主要在 SQL Server 的使用执照费用,以及同等任务所需要的云成本。

我在反复确认了这项工作是否真的有做的价值(从 SQL Server 改为 MySQL)后,讨论了一下具体实施方案。

移植的难点在于该项目大量使用了 SQL Server 的存储过程。几乎所有的业务逻辑都是人肉写在 SQL Server 的存储过程中的,大约有 20 万行。虽然 SQL Server 的存储过程和 MySQL 的差异不是特别大,但再靠人一点点重写成本上也不划算。

负责的这个同学说他考虑用 ChatGPT 来做翻译工作,并做了一点点预研工作。结论是,AI 可以辅助这件事,提高开发效率,但是,翻译结果还是需要人工来审校。工作量并不小,而且一旦出错,损失会很大。

我对 SQL Server 和 MySQL 都不熟悉,但我觉得既然都是 SQL 数据库,那么一一对译应当问题不大。但我认为应该选择一条渐进的路线,让项目可以一步步推进,每步都能直接看到结果。据此,我设想了这么一个方案:

  1. 先将 C++ 代码中所有涉及的 20 万行存储过程全部定位出来,改造这部分代码,为每个已有的存储过程都赋予一个唯一的 hashtag ,并把它们提取到单独的文件中。事后,我们可以根据 hashtag 直接定位到想干某件特定的事务。

  2. 做一个中间层,放在游戏服务器和 DB 之间,把所有的存储过程请求都串行化。改造通讯协议,将 hashtag (以及相关参数)放在协议层,让中间层可以了解每个请求想干什么,而不是直接让存储过程和数据库通讯。

  3. 同时启动 SQL Server 和 MySQL 两套数据库,中间层和两套数据库保持连接。一开始,可以把所有 SQL Server 的存储过程,根据 hashtag 转发到 SQL Server 上。然后,把 SQL Server 的数据同步到 MySQL 。因为有源码,我们还可以优化后一步的同步流程。比如事先在每个请求上标注该请求大致会影响到数据库中哪些数据,让同步更高效。因为游戏业务比较容易分类,所以标注也只是一个分类问题,工作量并不大。而数据查询,则在 MySQL 数据库上进行。

  4. 找到高频的存储过程,翻译成 MySQL 的存储过程。经过翻译的新版本,则由中间层转发到 MySQL 上运行,运行完毕后,再把结果从 MySQL 同步到 SQL Server 。

  5. 新业务在 MySQL 上开展。

不断迭代第 4 步,直到覆盖绝大多数需求,最后只保留很少的 SQL Server 资源,这样也可以达到降低成本的目的。


在这个方案中,实际上保留了两份完全相同的数据库,一份在 SQL Server ,另一份在 MySQL 中。我们把修改数据的操作集中在中间层做,以单个储存过程为单位对数据集做修改。假设有 A B C D E 五次修改,其中 A B C 是 MySQL 版本的,D E 是 SQL Server 版本的,我们并不需要每次操作都做结果同步。A B C 这三步连续修改是在 MySQL 上完成的,它们可以(并行)完成后再把结果同步到 SQL Server 再进行 D E 操作。

随着翻译工作的进展,越来越多的事务可以直接在 MySQL 上完成,这些事务也不再需要严格串行,对用户的影响也就越来越小。而保留在 SQL Server 上进行的操作只是增加了用户请求的延迟,并没有增加服务器的压力。整体来说,SQL Server 的配置可以逐步减少,达到削减成本的目的。

而在测试期间,一直可以通过增加一些额外手段(将事务在两侧都运行一次),从而可以以比对两个数据库数据的一致性的方式来检验过去一个阶段的工作的正确性。比起把 20 万行代码全部移植完再跑新版本来说,心里也会比较踏实。


对于这个方案,我并不想让它变成一个通用的数据库中间层,透明的对待 MySQL 和 SQL Server 两种服务器。它更像是一个迁移数据库的脚手架,会根据业务需要动态做调整。而且我们可以在源码层次做辅助配合,比如增加 hasgtag 这样的高阶信息,直接表明每个操作到底想做什么,会影响哪些数据等等。而且迁移是单向的,一旦一个 SQL Server 的存储过程被顺利移植到 MySQL 上,就不会再改回去。新业务也永远不会在 SQL Server 上开发。