« August 2024 | Main | October 2024 »

September 23, 2024

最近玩的几个游戏

这个月没有写什么程序。月初停下手头的开发工作,花了一周时间,作为 Indieplay 评委试玩了 200 多个参选游戏中的 100 多个。这个工作暂停之后,我就对前两个月对自己想做的游戏产生了许多疑惑。虽然写了不少代码,但仅限于基础玩法的外在功能:我实现了一整套类似边缘世界和缺氧里的工人系统,让小人可以在场景中活动起来,采集物资,建设建筑。让机器可以通上电运转起来,把原料加工为成品。但这些似乎只是一种模拟过程,而并非游戏。

我感觉自己对游戏到底想展现怎样的游戏体验没有清晰的认识。虽然在这篇采访中 也提到,(缺氧的最初设计是)“希望整个游戏运行在一个开放的(虽然简单的)模拟之上”。但我觉得模拟毕竟不是游戏,难以给玩家提供丰富的游戏体验。或者说,至少对于我这样的玩家,没有清晰的游戏目标和挑战是不行的。而且,实现一个丰富的游戏环境模拟面临的挑战我现在还无法评估,至少在当下,这不是我优先想做的东西。

我给游戏定下的基调是基地建设加生存挑战类型,或许应该有一些资源管理和 Roguelike 元素。工人管理或自动化元素是我比较喜欢的,但玩过几千小时类似游戏后,我感觉这些元素只是给予玩家体验的一种手段,并非目的。单独玩某个特定玩法,或许也能有趣,但体验却会大相径庭。

比如,我这个月花了不少时间玩 Shapez 2 。这是一个把自动化做到极限的游戏。玩家不再需要考虑能源、制造成本等问题,也没有敌对势力,只需要专心铺工厂,研究如何把工厂规模扩大并保持生产效率最大化。看起来, Factorio 关掉虫子后,也是在干这个事,但我玩下来体验其实是不同的。如果单纯想玩自动化规划,Shapes 显然更轻松有趣;但从游戏性上来说,我更喜欢 Factorio 一点。

我还玩了几天 The Crust 。这个游戏在我的愿望单里放了很久,一发布就开始玩了。我想这是一个 Factorio 和 Rimworld 的混合体。前半部分有很大的 Factorio 成分,玩到十几小时之后,又掺入了殖民地管理和工人分配的玩法。目前它处于 EA 阶段,感觉很多东西还不太成熟。仅就现在完成部分来说,我不是特别喜欢。它的自动化部分略显粗糙,殖民地管理部分又似乎不太完善。关键是交互体验非常糟糕(需要打磨),科技树的平衡更是一言难尽。而它又不像 Factorio 那样有一个坚实的游戏内核,可以通过 Mod 不断扩展玩法;玩起来的体验更依赖于设计好的场景来推动。

最近另一个让我略微失望的游戏是 Frostpunk 2 。一代是我最喜爱的游戏之一,这次 2 的豪华版可以提前 3 天玩游戏,我迫不及待就下单了。用了一天时间快速通关。玩这个游戏,有很大成分是我最近在思考生存类的基地建设游戏该怎样设计。如果没有一代珠玉在前,这也算是不错了。可惜玩过一,核心体验非常雷同。这是一个标准的由预设关卡驱动的基地建设游戏,无尽模式比较无趣。挑战预设剧本是我获得乐趣的主要来源。失败再挑战的循环,让我在一代中花了几十上百小时。但一旦理解了核心规则,抛开“通过玩家抉择来叙事”这个独特的体验,专心考虑如何提高各种数值,游戏不算太难:和一代一样,只需要快速发展科技,回避那些看起来符合短期利益的选择,不采用激进方案,就能达到最优解。这次的二代场面变得宏大,去掉了一代修房子安排工人的微观管理,让游戏体验变成了类似 Excel 表单中的各种进度条。这让我感觉体验不如一代。

和前面提到的 The Crust 一样,这个游戏也有超出同类游戏平均水平的画面质量。这类游戏拥有的高画质反而让我在玩之前就倒扣了期待分,我的这个直觉几乎每次都是对的。如果游戏画面无法帮助玩家更好的理解游戏内涵,那就毫无意义。比如 Frostpunk 2 ,玩家根本不需要关注里面的建筑细节,那么游戏画面精细的刻画建筑就是在浪费开发成本。玩家更关注每个区域的状态和功能,真不如直接给每个区块标记上颜色就够了。而现在默认的画面,看上去场景就是白茫茫一片,关键建筑,即使按住 Alt 凸显出来,还是没有区分度。甚至于,如果有个文本表单都比现在的华丽画面强(不至于让玩家找不到北)。

我最近几年对 Minimalist 极简游戏特别有好感。没有画面加成,极简风的游戏会把注意力放在游戏设计上。一旦核心玩法出众,就很难被掩盖。极简画风也不容易在游戏过程中分心,画面更注重表达游戏规则,学习成本通常更低。例如,我前几天完了一堆塔防游戏,发现最近的新作中,还是极简塔防 最为有趣。

最近玩的比较多的另一个有塔防元素的游戏是 Drill Core 。我感觉它受到了 Dome Keeper 的启发,但青出于蓝。目前在 steam 的评价中,有许多负面评价集中在挖掘过程里随机性带来的损失对体验的伤害。但我一口气玩了数十小时候,反而觉得那些是设计好的玩法,是游戏特点之一。例如挖掘过程中遇到的落石、喷火块、烦人的地龙,都可以通过合理的规划而避开。游戏似乎故意设计成无法具体对单个工人下指令,必须通过布置任务和设置优先级的方式这种间接的方式控制工人的行为。在充分了解规则后,这反而是一种挑战。只不过现在这种交互方式过于隐晦,而规则又不明确,导致有时体验比较糟糕。在微观管理为主的游戏中,玩家需要的其实是确定性规则,过于智能的 AI 未必是好事。这点我是在去年设计工厂类游戏中学到的:因为想为手机设计的缘故,局限于手机的不便交互,我们去掉了传送带,而使用更智能的无人机运营物流。智能规则导致了物流中的许多不确定性,反而没有传送带这种确定规则好玩了。

随机性带来的不确定性也未必是坏事。但围绕随机性的游戏体验应该是教会玩家做风险管理。例如我最喜欢的 Roguelike Rogue's Tale 就是这样一个风险管理游戏。我最近还发现了另一个被玩家批评随机性太强的游戏叫做 Derelict_Void 。我还没怎么玩,暂时不予评价。关注它是因为这个游戏似乎包含了我目前想做的游戏的各种元素:太空生存、基地建设、资源管理…… 看起来它受到更早的一个游戏 OutThere 启发:基于非常有限的资源探索宇宙,尽可能的活动下一个目的地。玩家需要非常小心的平衡氧气、水、有机物、燃料的使用,尽量养活合适数量的船员。没有和敌对势力的战斗(像 FTL 那样),但依然有极大的生存压力。

September 03, 2024

Ant 引擎的一些改进计划

我独自开发游戏已经有三个月了。这三个月里,我是 Ant Engine 唯一活跃用户,这是一个很好的机会来挖掘对于一个独立游戏开发者来说,引擎哪些地方有缺失。现阶段,我还是希望把精力放在游戏开发上多一些,所以引擎方面恰恰够用就好。虽然,完善引擎这件事做起来会更愉快,因为这些工作对于我比较顺畅,容易想清楚,游刃有余;而一个人开发游戏,更多的时候是手跟不上心而产生的烦闷。

我还是想挑战一下自己,把游戏设计好,实现好。引擎方面的事情,把想到的东西先记录一下。或许完成手头的游戏项目,沉淀更多,再回头做引擎,愉悦感更强一些。

首先,可视化编辑器 对我来说不重要。所以暂时就不维护了。我更需要的是一些快速验证眼下游戏设计中想法的功能,这些就在游戏 demo 中顺带实现就好,看起来没必要放在编辑器里。这和现阶段没有美术参与也有关系。因为对我自己做独立游戏来说,我不在乎开发进度,先做美术还是后做美术,区别不是很大。本来我自己就喜欢传统 roguelike ,几个 ascii 字符就能脑补所有的美术表现。我想,游戏原型阶段就不需要美术在编辑器里做创作了,用一些几何体就够用。这也是为什么我在三个月前最先完善的就是 Ant 引擎中预制几何体 这个功能的原因。

我在使用 Ant 引擎的时候,发现因为缺乏具体 API 文档而只能不断的阅读源代码(毕竟有很多模块不是我自己动手写的,无法全部了然于心)。而且并非每个模块的设计都满意,这让我经常有修改引擎的冲动。做了一段时间后,我找到一个方法来解决这个开发问题。我可以额外再做一个精简版的框架,按目前开发游戏的需求,从最基本的功能做起,逐步完善。这样就能隔绝引擎已经做好的部分:好用的模块直接做一些浅封装,有问题的部分可以多花些精力做不侵入(破坏老代码)的改进。

本来根据游戏类型的不同,使用引擎的方式就会有很大差异。我希望可以有不同的这样的框架针对具体类型游戏做二次封装。这样,在二次封装上写游戏的花,后面就可以更放心的裁剪底层实现。我更希望让 ECS 框架还原成更原始的设计:面向数据,避免添加太多的辅助模块。

最近还有许多工作是在 UI 上。我对 RmlUI 的方案还是比较满意的。毕竟类 web 的开发有极大的用户基础,各种边角被人打磨过。不过目前的一些实现细节,尤其是 UI 层和游戏层的消息通讯部分存在设计问题。

现在 UI 层和游戏渲染(以及逻辑)处于两个隔离的 Lua VM 中,跑在不同线程上,依赖消息通讯交换数据。引擎简单的封装了消息通讯过程,提供了 RPC 方法。但从游戏逻辑倒 UI 阻塞 RPC 调用,直接使用的话必定产生死锁。这是因为游戏逻辑通常放在 ECS 的一个 system stage 中执行,而处理 UI 层的 RPC 请求在另一个 stage 。为了回避这个死锁问题,需要小心的利用 ltask 的一些异步功能。我做了一些简单的封装后,情况好了一点。这个封装抽象出一个 model 对象,自动在两个层之间做数据同步(只同步差异部分)。在游戏逻辑这边设置 model 的状态,就可以直接在 UI 上展示出来。这个封装还很粗糙,需要我自己多做一些 UI 模块后再改进。

由此,我猜想 ECS 里面可能还需要提供一个 async 的 stage 可能好点。现在的 stage 里如果调用了 ltask.call ,就完全塞死当前帧了。加一个 async 的 stage ,让这里 yield 出去的流程,在下一帧回来这个stage 继续做。这样也可以取代 instance 创建的 onready callback 。只需要把一些消息处理过程放在 async stage 就可以更自然的写。前几个月就做过一点类似的尝试 ,感觉还没想好,暂时不打算把这个特性加到引擎中。


动画模块 是目前引擎比较欠缺的部分。只是我在做游戏原型时还用不上。如果未来做动作向的游戏,这方面的需求就更大了。这个的开发优先级比较低,等实际用起来再解决。

材质系统 看起来更值得改进。尤其是我在开发过程中,遇到一个简单的需求:运行时把一个对象改为半透明渲染,折腾了我好几天。最后我还是采用了去年开发游戏过程中使用的方案,为编辑器做好的预制件数据打上 patch ,为每个预制件预生成一个半透明材质的方式。然后在运行时根据需要,在不透明和半透明预制件中做选择(因为现在引擎不支持运行时给对象赋予完全不同的材质)。

说起这个半透明材质问题,我认为本质上还是性能优化问题导致的。理论上,我们可以让所有的对象都是半透明材质,把透明度调为 1.0 ,它就呈现出不透明的状态。调成 0 就消失了。但是,对于渲染来说,不透明和半透明(以及不显示)性能上有本质差别,这会导致不透明的 3d 物体和半透明 3d 物体底层渲染管线都有极大的差别,远非改个材质参数这么简单。或许在 2D 引擎中,这个差别并不大,但对开发者来说,最好不管是 2D 管线还是 3D 管线,都不必在意实现的困难,用起来设置个参数就可以了。这也是引擎要极力解决的问题。在这个(半透明)问题上,我和引擎开发团队的同学讨论了两个晚上,有了一些新的想法。以后有时间我想重构(并简化)相关底层代码。

目前,我不打算在手机平台上开发游戏。这存粹是个人对游戏体验的喜好:我对在触摸屏手机上玩游戏完全失去了兴趣。那么 Ant Engine 的最大努力:直接在开发机上对手机设备上的游戏损失调试,看起来意义就不大了。未来我想把为了实现这个特性而给引擎带来的复杂度做一些简化。尤其是远程调试、VFS 同步、触摸屏支持等。同时,可以增强许多 PC 开发上的体验:尤其是美术资源自动编译这块。我希望可以尽量减少额外的编译环节,让引擎能直接加载更多的通用格式的文件(图片、模型等)。

尤其是材质编译模块,是目前引擎中最为复杂的模块之一。我认为设计也是有问题的(不应该如此复杂)。这一块在上个月开发团队里做了一个晚上的讨论,改进方向下次专门写一篇 blog 介绍。

另外,还有一个大块的计划是重新用 Vulkan 编写 gfx 层,而不再使用 bgfx 这种跨平台方案。这也是后话了。相较用 Vulkan 实现新的 gfx 层,我更希望有机会好好做一套 2D 管线(以及独立的 2D gfx 层)。毕竟 2D 的 gfx 层要简单的多,可以把重心放在如何提供更好的(独立)游戏开发体验上。

想做的事情太多,一件件来吧。

Just for fun