1. Leaving Rust gamedev after 3 years (loglog.games)
离开Rust游戏开发:三年后的反思
核心问题与结论
作者作为一名小型独立开发者(2人团队),在多年使用Rust进行游戏开发并完成多个项目后,决定放弃使用Rust开发游戏。其核心原因是Rust语言的设计理念与独立游戏开发快速迭代、灵活试错的核心需求存在根本冲突。尽管投入了大量时间(超过3年,10万行代码),但许多根本性问题并未随着经验积累而消失。
主要痛点详述
1. 语言核心:借用检查器与迭代速度
- 强制重构,打断心流:借用检查器常在最不合时宜的时候要求重构代码,阻止开发者“先写出来,以后再优化”的常见策略。在游戏开发这种需求频繁变动的领域,这严重拖慢了迭代速度。
- “写好代码”的悖论:虽然重构能让代码更“好”,但对独立游戏而言,快速验证玩法想法比代码的长期可维护性更重要。Rust迫使开发者在“测试想法”和“优化代码”之间做出选择。
2. 架构模式:ECS的过度推崇与误导
- 解决错误的问题:ECS(实体组件系统)在Rust社区被推崇,很大程度上是为了解决语言自身的借用和所有权问题,而非出于游戏设计需要。
- 不必要的复杂性:作者认为,对许多游戏而言,使用代际 arena(如 thunderdome) 管理实体就足够了,完整的ECS架构引入了不必要的复杂性和抽象成本。
- “正确方式”的迷思:Rust社区有时将ECS等特定模式上升到近乎教条的程度,忽略了其他更直接、更适合特定游戏的实现方式。
3. 生态系统与工具链
- 编译时间:虽有改善,但过程宏(proc-macros,如serde)会导致增量编译缓慢,迫使开发者进行繁琐的代码拆分以优化编译。
- 缺乏热重载:与C#/.NET或Unity相比,Rust缺乏成熟、通用的热重载能力,这极大地影响了调试、调参和UI打磨的效率,是作者选择回归Unity的首要原因。
- GUI困境:Rust缺乏适合游戏开发的GUI库。现有库要么过于通用,要么不适合制作高度定制化、富有表现力的游戏UI(如按钮动效、粒子效果)。
- 生态系统存在“炒作”倾向:许多项目因出色的宣传和文档获得关注,但实际可用性和成熟度不足。一些实用但“不够纯粹”(如使用全局状态)的优秀库(如Macroquad)反而被低估。
4. 理念冲突
- 单线程游戏与全局状态:大多数游戏逻辑本质上是单线程的。Rust对全局状态的严格限制(基于安全考虑)带来了不必要的复杂性,而简单的解决方案(如
Rc<RefCell<T>>)又可能引发运行时崩溃。 - 过度工程:Rust鼓励泛化、分离关注点等“正确”的工程实践,但这有时会导致代码过于复杂和抽象,反而阻碍了快速实现和理解简单的游戏逻辑。
- 上下文对象与灵活性不足:为满足借用规则而设计的“上下文对象”模式,在添加新功能时常常需要重构,缺乏其他语言中的灵活性。
Rust的优点
尽管决定离开,作者仍肯定了Rust的几个方面:
- 编译即正确:当代码符合Rust范式时,编译通过后往往能正常工作。
- 默认高性能:Rust代码通常具有优秀的运行时性能。
- 出色的枚举和特征系统:在适合的场景下非常强大。
- 强大的工具链:
rust-analyzer尽管偶有问题,但极其有用。
未来计划
作者团队将回归Unity开发,以利用其成熟的编辑器、完善的工具链(特别是热重载)和庞大的生态。他们计划将自研的2D游戏框架Comfy的渲染器从wgpu移植到Macroquad,以获得更好的平台支持和维护稳定性。
总结
本文并非对Rust语言的全面否定,而是从一名追求商业可行、快速发布的独立游戏开发者的视角出发,指出Rust当前的语言特性、生态系统和社区文化与这一具体开发目标之间存在的显著摩擦。作者的结论是:对于需要高强度迭代、玩法探索和快速交付的独立游戏开发,其他工具(如Unity)提供了更顺畅的路径。