信息化管理系统 | 数字孪生 · 智慧园区 · 数字大屏 | App · 微信 · 小程序 | 元宇宙 · 区块链 · 3D展厅 | 虚拟仿真系统 | 新零售电商

三年全职 Rust 游戏开发,真要放弃 Rust 吗?(4)

文章讨论了几种不同的看待 ECS 的角度。

  1. ECS 作为动态组合工具

ECS 允许开发者将不同的组件(数据单元)动态地组合到实体(游戏中的对象或角色)上。这种方式非常灵活,可以根据游戏逻辑的需要在运行时添加、移除或修改组件。例如,一个游戏角色(实体)可以具备位置(Transform 组件)、健康状态(Health 组件)、以及武器装备(Weapon 组件)。这种动态的组合使得开发者可以创建复杂且多变的游戏逻辑,同时保持代码的模块性和可维护性。

  1. ECS 作为性能优化工具

在 ECS 中,组件通常按类型存储在紧凑的数组中,这种存储方式称为 "结构化的数组"(也有时借用数据术语称作 "数据的数组",Data-Oriented Design)。这样做可以显著提高内存的局部性,因为相关的数据存储在内存中的位置更加靠近,CPU 在访问这些数据时可以更有效地利用缓存。例如,如果系统需要处理所有实体的健康状态,它可以连续地访问存储所有健康组件的数组,而不是跳转到分散存储的对象中去找健康数据。这种方法尤其适合于需要频繁处理大量数据的场景,如物理模拟或复杂的游戏 AI 计算。

  1. ECS 简化 Rust 借用检查器的应用

ECS 的另一个重要优势是它能够简化 Rust 借用检查器的管理。Rust 的借用检查器确保了内存安全和数据访问的正确性,但在传统的面向对象编程中,管理复杂的对象和生命周期关系可能变得非常困难。使用 ECS,开发者可以通过将数据和行为分离,更容易地符合 Rust 的借用规则,从而简化开发。实体在 ECS 中通常是轻量级的标识符,组件和系统则是独立的,这使得跨系统的数据访问可以在不违反借用规则的情况下进行。

  1. ECS 作为动态创建的 generational arenas

在 ECS 架构中,实体通常由一组组件构成,每个组件都可能存储在一个 generational arena 中。这种结构允许系统以非常高效的方式添加、删除和修改组件,同时确保引用的有效性和安全性。动态创建的 generational arenas 指的是这样一种系统:不仅数据是动态管理的,而且数据容器(即 arenas)本身也可以根据需要动态创建和配置。

  1. ECS 就是 Bevy

这部分是作者开玩笑。因为 Bevy 在 Rust 社区算是 ECS 的代表,而且 Bevy 与 ECS 绑定很深,包括 UI 都用 Bevy。但作者也指出,虽然他可能在很多事情上持不同意见,但很难否认 Bevy 对 ECS API 和 ECS 本身的人体工效学改进。

另外作者也提到了 Unity DOTS,它本质上是他们的“ECS”(以及其他面向数据的东西)。作者认为在 Unity 领域中不会找到一个人会认为 DOTS 是一个不应该存在的糟糕功能;但也不认为有人认为 DOTS 就是未来的全部,游戏对象应该从存在中被抹去,所有的 Unity 都应该转移到 DOTS。

那些使用过 Godot 的人可能会看到一个类似的观点。特别是那些使用 gdnative (例如通过 godot-rust )的人,尽管节点树可能不是适用于所有情况的最佳数据结构,但对于许多事情来说,它们确实非常方便。

但是 Rust 社区里,作者认为 Bevy 的 “ECS everything” 理念,给开发者带来了不便。一个明显的例子,也是作者认为 Bevy 的一个重大失败点,是 Bevy 的 UI 系统,这已经是一个痛点了一段时间,特别是与“我们今年一定会开始开发编辑器!”这类承诺相结合。

ECS 在 Rust 社区从在其他语言中视为的工具变成了几乎是一种“宗教信仰”:应该使用它,因为它是纯粹和正确的,因为这样做是正确的方式。 Rust 常常感觉就像与青少年讨论他们对任何事情的偏好一样。他们表达的往往是非常强烈的观点,而不是很多细微差别。编程是一项非常微妙的活动,人们经常不得不做出次优选择以及及时地得到结果。在 Rust 生态系统中,完美主义和对“正确方式”的迷恋常常让我觉得这门语言吸引了那些对编程较新且容易受影响的人。

其实在 Rust 社区 ECS 并不仅仅用于实现游戏,比如,在可视化系统 rerun[8] 中也应用了 ECS 架构。

因此,不要把 ECS 当作万能灵药

"通用化系统不会带来有趣的游戏玩法"

作者罗列了他认为能够创造出好游戏的一些因素:

  • 大多数关卡流程应该是手工设计的。这并不意味着“线性”或“故事”,但确实意味着“对玩家何时看到什么有很多控制”。
  • 在各个关卡中精心设计的个性互动。
  • VFX 不是基于有很多相同的粒子,而是时间同步的事件(例如,多个不同的发射器按手工设计的时间表触发)在所有游戏系统中工作。
  • 通过多次迭代的游戏玩法测试、实验和丢弃不起作用的内容。
  • 尽快将游戏发布给玩家,以便对其进行测试和迭代。如果没人看到它,当它发布时,没人关心的机会就越大。
  • 独特而难忘的体验。

作者认为,游戏开发的本质不是建造物理模拟,不是建造渲染器,不是构建游戏引擎,不是设计场景树,也不是设计具有数据绑定的反应式UI,而是仔细思考玩家互动并设计它们

这里的一个好的游戏示例是《以撒的结合》,这是一个非常简单的肉鸽(roguelike)游戏,拥有数百种可以以复杂、互动和深入的方式修改游戏的升级。这是一个拥有许多系统相互作用的游戏,但它也完全不是通用的。这不是一个拥有500种“+15%伤害”的升级的游戏,而是许多升级是“炸弹粘在敌人身上”或“你射出激光而不是弹药”或“你每级杀死的第一个敌人将不再出现”。

你不是通过在地下室里坐一年,思考所有边缘情况并建立一个通用系统,然后 PCG所有升级来制作一个好游戏。你是通过构建一些简单机制的原型并让人们玩它,看看核心内容是否有效,然后再添加更多东西让人们再玩一次。其中一些互动必须通过在游戏中玩了许多小时、尝试了许多不同的事情后对游戏的深入了解来发现。

《Thronefall》作者 Jonas Tyroller 在他关于游戏设计的视频[9]中非常好地解释了这一点:“一个好的游戏不是在实验室中精心设计的,而是由一个精通该类型的大师级玩家兼开发者制作的,他了解设计的每个方面,并在达到最终设计之前尝试过许多失败的尝试。一个好的游戏是通过摒弃许多糟糕的想法,通过非线性的过程来制作的”。

1人开发、Steam好评97%,这款“超简化”RTS塔防游戏赢得满堂彩!由GrizzlyGames 工作室发布的独立游戏《Thronefall》,自2023年8月2日抢先体验版上线Steam后,游戏最高在线人数曾一度达到6723,近期同时在线人数依然维持在3000以上。游戏发布至今已有八千多条玩家评测,其中高达97%为好评,足以见得玩家对《Thronefall》的高度认可。

一个更灵活的语言会允许游戏开发者立即以一种粗糙的方式实现新功能,然后玩游戏,测试它并查看这个功能是否真正有趣,可能在短时间内做这些迭代。而当Rust开发者完成他们的重构时,C++/C#/Java/JavaScript开发者已经实现了许多不同的游戏玩法功能,玩了很多游戏并尝试了所有这些功能,对他们的游戏应该朝哪个方向发展有了更好的理解。

"制作有趣且有趣的游戏是关于快速原型和迭代,Rust 的价值观与此完全不同"

作者认为,Rust 社区已经采纳了这种对 Rust 相关事物的无情积极性和赞美的观念,完全将自己与外界隔离了开来。真实的游戏世界并不那么友好。Steam 上的玩家并不在乎某个东西是用 Rust 制作的,他们也不在乎它花了多长时间制作,他们也不在乎代码是否开源。他们关心的是看游戏,并在几秒钟内能够判断这是否会是浪费时间,或者是一些潜在有趣的东西。玩家不关心开发者,只是在几秒钟内看游戏是正确和可取的,但至少这让我们保持诚实。这使得游戏只关注游戏本身,而不关注其他任何事情,因为最终,游戏和玩游戏的体验才是最重要的。

这其实跟 Rust 社区没有关系,任何游戏或应用、产品的用户都不会在意它是不是 Rust 实现的。只不过作者作为一名 Rust 开发者,自身在这个圈子里。

代码质量是保证用户体验的一个因素,只要不是过度追求代码质量即可

作者显然也明白,他说他当然同意这个观点,当有人按下播放按钮时游戏崩溃,或当你损坏存档文件并且玩家失去进度时,这绝对是影响玩家体验的。

但他认为所有这些都完全忽略了对玩家来说重要的事情。有很多情况下,人们的进度被清零,但他们仍然会回到游戏中并再次玩它,因为游戏太好了。作为玩家,他已经做过这种事情不止一次。

前提得是 「好游戏」吧?

作者的意思很明确:应该专注于好游戏,而非好代码。因为 Rust 的强制重构,导致他把精力耗费在实现「好代码」上,而非「好游戏」上。

 

 

 

如有侵权请通知删除,谢谢!

本文转自;三年全职 Rust 游戏开发,真要放弃 Rust 吗?-腾讯云开发者社区-腾讯云 (tencent.com)