《我用Rust开发了一款游戏,耗时六年,现已发售,随便问》(2024) 精华摘录

Lobsters Hottest 新闻

摘要

对《Way of Rhea》开发者AMA问答的精选内容摘录。这是一款用Rust历时六年打造的解谜游戏,内容涵盖Rust游戏开发的痛点、自研引擎的取舍权衡,以及独立游戏发行的经验教训。

<p><a href="https://lobste.rs/s/dodzdb/highlights_from_i_spent_6_years">评论</a></p>
查看原文
查看缓存全文

缓存时间: 2026/10/11 23:39

# 《我用 Rust 开发了 6 年游戏,终于上线了,AMA》精华内容 来源:https://gamesbymason.com/blog/2024/6-years-in-rust-ama 我最近发布了 Way of Rhea (https://store.steampowered.com/widget/1110620/?utm_campaign=ama),这是一款我从 2018 年起用 Rust 开发的解谜游戏。如果你喜欢《Braid》、《The Talos Principle》或《Portal》这类游戏,你大概率会喜欢它: 上线后,我在 r/rust_gamedev (https://www.reddit.com/r/rust_gamedev/comments/1cwqcfl/i_spent_6_years_developing_a_puzzle_game_in_rust/) 发起了 AMA,大家提出了非常多很棒的问题! 以下是从 AMA 中精选的精华内容,并做了一些编辑以提高可读性。 ## 目录 (https://gamesbymason.com/blog/2024/6-years-in-rust-ama#table-of-contents) - 目录 (https://gamesbymason.com/blog/2024/6-years-in-rust-ama#table-of-contents) - 关于 Rust 的问题 (https://gamesbymason.com/blog/2024/6-years-in-rust-ama#questions-about-rust) - 是什么让你决定使用 Rust? (https://gamesbymason.com/blog/2024/6-years-in-rust-ama#what-made-you-decide-to-use-rust) - 使用 Rust 最让你沮丧的部分是什么? (https://gamesbymason.com/blog/2024/6-years-in-rust-ama#what-was-the-most-frustrating-part-of-using-rust) - 你用了哪些库和 crate? (https://gamesbymason.com/blog/2024/6-years-in-rust-ama#what-libraries-and-crates-did-you-use) - 关于 Steam Input 的一些说明... (https://gamesbymason.com/blog/2024/6-years-in-rust-ama#notes-on-steam-input) - 生态系统的变化对项目有影响吗? (https://gamesbymason.com/blog/2024/6-years-in-rust-ama#have-ecosystem-changes-affected-the-project) - 你怎么看 LogLog 的《离开 Rust 游戏开发》博客文章? (https://gamesbymason.com/blog/2024/6-years-in-rust-ama#what-do-you-think-of-loglogs-leaving-rust-gamedev-blog-post) - 关于引擎的问题 (https://gamesbymason.com/blog/2024/6-years-in-rust-ama#questions-about-the-engine) - 自定义引擎给项目增加了多少时间? (https://gamesbymason.com/blog/2024/6-years-in-rust-ama#how-much-time-did-making-a-custom-engine-add-to-the-project) - 你的崩溃报告策略在实践中效果如何? (https://gamesbymason.com/blog/2024/6-years-in-rust-ama#how-did-your-crash-reporter-strategy-work-in-practice) - 你是如何处理窗口管理和输入的? (https://gamesbymason.com/blog/2024/6-years-in-rust-ama#how-did-you-handle-windowing-and-input) - 为什么你不使用现成的脚本语言? (https://gamesbymason.com/blog/2024/6-years-in-rust-ama#why-didnt-you-use-an-existing-scripting-language) - 重新加入 macOS 支持有多难? (https://gamesbymason.com/blog/2024/6-years-in-rust-ama#how-hard-would-it-be-to-add-support-for-macos-back-in) - 你对引擎和脚本语言未来的计划是什么? (https://gamesbymason.com/blog/2024/6-years-in-rust-ama#what-are-your-plans-for-the-engine-and-scripting-language-going-forward) - 关于游戏开发的问题 (https://gamesbymason.com/blog/2024/6-years-in-rust-ama#questions-about-game-development) - 你认为怎样才算一次成功的发行? (https://gamesbymason.com/blog/2024/6-years-in-rust-ama#what-do-you-consider-a-successful-launch) - 关于活动的补充说明... (https://gamesbymason.com/blog/2024/6-years-in-rust-ama#side-note-on-events) - 解谜平台游戏不是最难在 Steam 上卖出去的类型之一吗? (https://gamesbymason.com/blog/2024/6-years-in-rust-ama#arent-puzzle-platformers-one-of-the-hardest-genres-to-sell-on-steam) - 你学到的最重要的经验教训是什么? (https://gamesbymason.com/blog/2024/6-years-in-rust-ama#what-are-the-most-important-lessons-you-learned) - 你是怎么找到 beta 测试者的? (https://gamesbymason.com/blog/2024/6-years-in-rust-ama#how-did-you-find-beta-testers) - 关于以反馈为核心的社区的补充说明... (https://gamesbymason.com/blog/2024/6-years-in-rust-ama#side-note-on-feedback-focused-communities) - 关于评测的补充说明... (https://gamesbymason.com/blog/2024/6-years-in-rust-ama#side-note-on-reviews) - 为什么你要做封闭测试? (https://gamesbymason.com/blog/2024/6-years-in-rust-ama#why-did-you-do-a-closed-beta) ## 是什么让你决定使用 Rust? (https://gamesbymason.com/blog/2024/6-years-in-rust-ama#what-made-you-decide-to-use-rust) 在用 Rust 之前,我在做一个 C++ 游戏引擎。一个朋友一直在劝我试试这门很酷的新语言,但我当时比较怀疑,一直没给它机会。 后来有一次,我被 CMake 的某些愚蠢问题搞得不耐烦了(具体细节已经记不清了),决定休息几天,换点别的东西捣鼓。我找到了 Steve Klabnik 的 Rust 程序设计语言一书,从头到尾读了一遍,我记得那当时是官方推荐资料。 让我震惊的是,居然存在这样一门替代性的底层语言,它内置了构建系统、内置的单元测试和文档生成器、代数数据类型、基于非异常的错误处理等等。知道有这些替代方案之后,就很难再为自己继续使用一门摩擦力这么大的语言找到理由了。内存安全方面当然也很不错,但作为一个开发单人游戏的开发者,这对我来说并不是首要考虑因素。 从那以后,我就非常热衷于推动尽可能地从 C/C++ 迁移出去。我也是 Zig 社区的活跃成员,并且是 Zig Software Foundation (https://ziglang.org/zsf/) 的董事会成员。我知道互联网上倾向于把这些努力当作相互竞争的体育队伍来看待,但我觉得这偏离了重点。 当你是一个初学者的时候,会觉得把时间投入到"正确的"语言上很重要——否则就全浪费了。为了避免承受这种焦虑,新手程序员往往会告诉自己他们使用的语言或工具是完美无缺的,然后对任何批评它的人开火。 更好的未来是多个高质量底层语言相互制衡的未来。 我有我自己的观点,但我建议初学者少纠结于编程语言的选择,而那些想进入游戏开发领域的人应该考虑所有可用的工具,选择最适合自己当前需求的。 ## 使用 Rust 最让你沮丧的部分是什么? (https://gamesbymason.com/blog/2024/6-years-in-rust-ama#what-was-the-most-frustrating-part-of-using-rust) 编译时间!除了编译时间之外…… 我写的是游戏引擎,这意味着有时候我需要做底层的位操作之类的东西。这类东西本身就不容易做对,在 Rust 里更是难上加难。Unsafe Rust 的文档写得很差,用起来也很难,而且当你在网上求助时,人们表现得好像你使用了 unsafe 就是在犯什么罪。 Rust 的设计还基于这样一个预期:你只做两种分配——堆分配和栈分配。如果你真的想,你*可以*为代码库的不同部分实现自定义分配器,但这是在逆着设计走。 Rust 没有内建的反射支持也挺让人沮丧的。 从生态系统来看,有时候感觉我们的目标不对。我记得 2000 年代初 OOP 非常流行,如果你抱怨 OOP 没有帮你实现目标,人们会告诉你你只是需要更用力地 OOP。Rust 有时候给我一种类似的感觉。所有这些范式只有在影响一件事的时候才有意义:你的软件的最终用户。 我认为避免这个陷阱同时又推动更新更好的范式的方法是把事情做到底。如果你在构建一个音频库,也用它构建一个音乐播放器。如果你在构建一个游戏引擎,用它发布一款真正的游戏。这些例子不是在针对任何人,我只是想到了我脑海中最先浮现的两个想法。 通过把事情做到底,你可以看到你的决策如何影响最终用户,即使从决策到最终用户之间有很多曲折。这能让你保持务实。 ## 你用了哪些库和 crate? (https://gamesbymason.com/blog/2024/6-years-in-rust-ama#what-libraries-and-crates-did-you-use) 我用了不少 crate 和库,但没有什么是"关键依赖"的。特别值得一提的有…… 我用了 gl (https://crates.io/crates/gl) 来获取 OpenGL 函数指针。scopeguard (https://crates.io/crates/scopeguard) 在这里也非常有用——RAII 和 OpenGL 这类 API 搭配得不太好,scopeguard 本质上是给 Rust 加上了 defer,让这类代码好写多了。 窗口管理和键盘/鼠标输入的代码我自己写的,但在卡住的时候会参考 SDL (https://github.com/libsdl-org/SDL)。这活儿挺烦人的——我下一款游戏大概会用 SDL3——但自己动手做了之后学到了很多。 我还用了 notify (https://crates.io/crates/notify) 来获取文件变更通知以支持热替换,以及各种 STB (https://github.com/nothings/stb) 头文件来处理像解析 TTF 这样的事情。 reqwest (https://crates.io/crates/reqwest) 对崩溃报告很有用。 有些人问我是否用了某个库来辅助解析脚本语言。我个人不太喜欢解析器库——写解析器起初看起来很棘手,但实际上快速写一个递归下降解析器通常很容易。在学校里他们会告诉你递归下降对常见文法来说功能不够强大,理论上他们是对的,但在实践中你可以轻松绕过大多数问题——或者干脆设计一个更简单的文法。 如果你对这类东西感兴趣,这里 (https://craftinginterpreters.com/contents.html) 有一本关于编写编译器的很棒的资源。 我使用了 Steam Input (https://partner.steamgames.com/doc/features/steam_controller) 来支持手柄。最终效果不错,但我以后不会再用它了。 ### 关于 Steam Input 的一些说明... (https://gamesbymason.com/blog/2024/6-years-in-rust-ama#notes-on-steam-input) Steam Input 是 Valve 的输入重映射功能。玩家可以在一个可能支持也可能不支持手柄的游戏里,把手柄重映射为键盘行为,从而获得他们想要的操作方式。 这部分是不错的。 Steam Input 还有一个面向开发者的部分,提供以下 API: - 支持你能想到的每一种手柄的输入 - 游戏内 UI 用手柄按键图标 - 输入层 - 手柄重绑定 UI - 访问震动、手柄 LED 等功能 - 还有更多…… 问题在于这会把你绑定到 Steam 商店上,而且,它的实现完全是坏的。输入层从根本上就是有问题的,在不同平台上的表现不同,而且是以破坏游戏体验的方式不同。实际的输入行为也有细微的差异,并且似乎和 Steam Overlay 的一些奇怪 bug 绑定在一起。手柄重绑定 UI 有时也不显示,等等。 你必须通过 Valve 发明的一种领域特定语言来设置手柄绑定。这种语言的文档写得很差——示例经常有语法错误或者干脆是错的——而且几乎没有错误处理。 让这些配置文件正确的唯一方法是尝试通过他们的 UI 设置然后保存,但祝你好运弄清楚该怎么做,以及怎么把结果附加到你的构建中! 而且 UI 经常生成像这样的代码,看起来*像是*错误的但实际能工作,所以我想这就是正确的吧……? `` "binding" "game_action GameControls Action_Interact, , " `` ## 生态系统的变化对项目有影响吗? (https://gamesbymason.com/blog/2024/6-years-in-rust-ama#have-ecosystem-changes-affected-the-project) > 过去 6 年 Rust 游戏开发生态发生了很多变化。你说你写了自定义游戏引擎,但在这段时间里你是否需要更新或更换任何底层库?是否有一些由 Rust 或底层库的外部变化所导致的重大改动? 因为我几乎从零开始写了所有东西,所以不需要改太多。你当然可以通过引入更多依赖来加快进度,但我通过自己动手学到了很多,并且避开了这类变动。 ## 你怎么看 LogLog 的《离开 Rust 游戏开发》博客文章? (https://gamesbymason.com/blog/2024/6-years-in-rust-ama#what-do-you-think-of-loglogs-leaving-rust-gamedev-blog-post) *参考文章 (https://loglog.games/blog/leaving-rust-gamedev/)* 我基本同意他们文章中的所有观点,不过我在 ECS 的看法上已经转了一圈,现在觉得它是一个有用的范式——我在这次演讲 (https://gamesbymason.com/blog/2023/game-engines-are-art-tools/) 中有提到。我还有他们文章没涉及到的一些额外抱怨,在[这里](https://gamesbymason.com/blog/2024/6-years-in-rust-ama#what-was-the-most-frustrating-part-of-using-rust)。 我最近不怎么上网,因为忙着上线的事,我是因为一个朋友把文章发给我才看到的。我希望人们对它的反应是:"哇,来自一个真正在做产品的人的优秀反馈,让我们想想怎么最好地解决这些问题!" ## 自定义引擎给项目增加了多少时间? (https://gamesbymason.com/blog/2024/6-years-in-rust-ama#how-much-time-did-making-a-custom-engine-add-to-the-project) 我觉得人们倾向于假设我花了六年做游戏是因为引擎占用了所有时间,但实际情况并非如此。我的大部分时间都花在内容上。花了那么长时间是因为我最初是个业余爱好者,不知道该把精力集中在正确的事情上。 脚本语言是我在开始游戏之前做的一个业余项目。如果不把它算进去的话,我觉得引擎开发大概占了 20%-30% 的开发时间。当然,这并没有考虑我自建的引擎是否比我原本会用的其他方案更高产。我觉得算是喜忧参半吧? 我在过去的工作和像 LUCID (https://store.steampowered.com/app/1717730/LUCID/) 这样的外包项目中使用过现成的引擎。 使用现成引擎当然工作量少得多,但同时你对工作流程的控制力也弱得多——比如我发现热替换非常高效,虽然所有主流引擎都声称支持,但在实践中它们并不真正支持。 在自定义引擎中做游戏有点像是一种高速度低加速度的事业。实际体验因人而异。 ## 你的崩溃报告策略在实践中效果如何? (https://gamesbymason.com/blog/2024/6-years-in-rust-ama#how-did-your-crash-reporter-strategy-work-in-practice) > 我几年前读过你关于崩溃报告器的博客文章,所以我很好奇现在游戏已经发布了,"将游戏作为子进程运行"这个方案整体表现如何?你在发行时还坚持用了它吗,还是在这些年里遇到了一些意料之外的问题? 相关的博客文章在[这里](https://gamesbymason.com/blog/2021/how-to-write-a-crash-reporter/),Subtale 还基于这篇文章创建了一个 Rust 库 (https://github.com/subtalegames/cortex)。 它表现得相当好——我确实用它捕捉到了一些真正的问题——不过正如有人指出的,没有独立的可执行文件意味着它无法报告缺失的 DLL。这不是大问题,因为我主要依赖操作系统库,但不幸的是这对 libc 来说可能是个问题,我之前没有考虑到这一点。 这挺让人沮丧的,因为我用 libc 的东西并不多,但我搞不清楚怎么配置 Rust 只使用 musl 之类的,所以目前我不支持较老版本的 Ubuntu(Steam 上列出的最低版本)。 把崩溃日志直接发送到我的 Discord 频道比起让玩家自己发给我来说确实好很多,但它的人体工学(易用性)还可以好很多。我收到的错误不多,所以大概还行。 话虽如此,虽然崩溃报告器经受住了考验,但我目前正在为一个名为 Magic Poser (https://magicposer.com/) 的美术工具编写一个崩溃报告器(我为它做了一些引擎工作),我觉得我现在能写出一个好得多的崩溃报告器。等 Magic Poser 的崩溃报告器完成后,我会发布一篇新的博客文章

相似文章

我对游戏开发的看法错了

Lobsters Hottest

《Burst》的开发者回顾了在游戏难度平衡方面学到的经验教训,以及添加小费罐的决定,突出了独立游戏开发的挑战。

用 Rust 重写

Hacker News Top

本文评估了2026年的‘Rewrite It In Rust’运动,讨论了现实世界中的性能提升、诸如新错误和平台支持等挑战,并提倡增量重写而非完全重写。