Elytra
Blog游戏引擎

为什么要自己写游戏引擎?

从 C++ 自研引擎到 Rust/Bevy 的再次尝试,思考技术自主权的价值、重复造轮子的代价,以及 AI 时代真正稀缺的迭代能力。

好多年前,我曾经用 C++20 为自己的沙盒体素项目 Ethertia 写过一套引擎。它有 OpenGL 和 Vulkan 两套渲染后端,界面工具主要靠 ImGui 拼凑。那时没有今天这样强大的 AI 编程助手,很多东西都得自己一点点写。

最初倒没有想得那么宏大。从用 Java 模仿 Minecraft,到后来用 C++ 尝试制作更真实的版本,我一直喜欢折腾底层。能够自己掌控系统如何运作、打磨每个技术细节,本身就让我很有成就感。

但后来我逐渐发现,自己花大量时间实现的 Shader 热重载、材质系统、渲染抽象,在成熟引擎里早已有了更完善的答案。即使做出来,效果、工具体验和可靠性也未必比别人好。更何况,我还没有一套真正好用的编辑器。

这段经历当然不是白费:图形学和引擎架构的许多知识,恰恰是在自己动手时才真正理解的。只是当目标从「学习如何制作引擎」变成「完成一款游戏」,同样的投入开始显得不那么划算。

于是,一个一直没有消失的问题又回来了:我们为什么要自己写游戏引擎?

1自研引擎,究竟想获得什么?

自己写引擎并不天然比使用 Unity、Unreal 或 Godot 更高级。它真正提供的是决定底层规则的自由:数据如何组织、对象如何更新、渲染如何执行、哪些抽象应该存在,以及哪些根本不需要。

这种自由在两种情况下尤其有价值。

其一,引擎本身就是探索目标。如果希望理解渲染器、内存管理、ECS、并行调度或资源系统,那么自研就是一种很好的学习方式。做不出商业游戏,也不代表没有成果。

其二,游戏的独特体验需要特殊的技术结构。通用引擎必须照顾大量不同项目,它提供的是尽可能宽的能力边界,而不是为某款游戏精心设计的最短路径。

Teardown 是很典型的例子。可破坏的体素环境不是一个可有可无的特效,而是游戏世界的基本规则。开发者为此建立了专用的体素、物理和光照技术。自研技术在这里直接支撑了游戏的玩法身份。1

但「想做得更快、更小、更优雅」还不足以单独构成自研理由。真正需要追问的是:现有工具究竟限制了什么?绕过这层限制所获得的价值,是否大于长期维护成本?

2不必从零开始,也能拥有自己的引擎

过去谈起自研引擎,很容易想到从窗口创建、输入处理、图形 API、资源加载开始,最后搭出一个完整的 Runtime 和 Editor。我的 C++ 项目就走过这条路。

但这不是唯一选择。

Rust 生态中的 Bevy 提供了另一种思路:以 ECS、调度和插件组合系统。它本身是免费开源的通用游戏引擎,使用 Bevy 并不等于自研引擎;但开放和模块化的架构,让开发者可以根据需要替换或扩展内部系统。2

Tiny Glade 更有意思。它用 Rust 开发,复用了 Bevy 的 ECS、调度等基础能力,同时围绕程序化建筑和画面表现构建自己的技术。它既不是完全从零开始,也不是直接接受一个通用引擎的全部默认方案。3

这揭示了一个重要区别:复用基础设施,与放弃技术自主权,并不是同一回事。

真正值得自己设计的,也许只是游戏中不可替代的几个部分:体素数据结构、地形生成、世界模拟、程序化几何,或者 Modding 系统。至于窗口、输入、音频、导入流程和跨平台打包,没有必要因为想做一个独特的世界,就把它们全部重新发明一遍。

这也不是「传统面向对象引擎」与「现代 ECS 引擎」的简单对立。C++ 并不会因为年代久远就失去价值,Rust 和 ECS 也不会自动带来优秀架构。数据模型、工作流与具体需求是否契合,比语言和范式的标签更重要。

3最昂贵的代价,不只是代码量

最近,我又因为看到 AI 辅助开发的 PhotoCraft,重新打开了搁置约两年的 Rust/Bevy 沙盒项目 Ethertum。我以为现在可以把大部分代码交给 AI,终于摆脱当年手写 Rust 的痛苦。

结果十多个小时过去,我却再次决定停下。

最难受的不是 AI 不会写,而是反馈循环太长:等待构建、处理报错、调整配置、再次构建,好不容易运行起来,AI 重构的 UI 又普通得令人失望。尤其是更换构建参数后,大量缓存可能无法复用,让等待进一步放大。

这不是说 Bevy 天生要编译几个小时。它有动态链接、链接器优化等专门的开发配置;Cargo 也有增量构建机制。不过不同编译参数或依赖特性可能触发重编译,工具链的正确配置本身也是成本。4 5

更重要的是,编译时间只是迭代成本的一部分。编辑器、调试能力、场景可视化、资源工作流和工具成熟度,同样决定从一个想法到看到结果究竟有多远。

过去,一个小时写代码、几分钟编译,也许还能够接受。今天 AI 可能几分钟就完成修改,编译、启动、检查和返工却不会同步消失。于是瓶颈从「写得出来吗」转向了「能多快确认它真的正确、好用、好看」。

对于游戏,这尤其关键。玩家手感、视觉风格和交互反馈,很难只靠阅读代码判断。游戏不是编译出来就完成了,而是在一次次试玩中被塑造出来的。

4未来会出现大一统游戏引擎吗?

既然成熟引擎已经积累了如此多的工程经验,未来是否只需要一个最强的通用引擎?这让我想到大模型:越来越多应用直接建立在少数强大的基础模型之上,而不是每个领域都从头训练自己的模型。

游戏引擎可能也会沿着「更多能力成为公共基础设施」的方向发展。但完全统一并不容易。

一款 VR 游戏在意延迟和稳定帧时间;Teardown 在意可破坏体素的表示与模拟;大型开放世界要管理庞大的资产和流送;一个极简独立游戏则可能更重视体积、透明性和开发自由。它们需要的抽象有时不仅不同,甚至相互冲突。

所以我更期待的是基础设施趋于通用,特殊系统保持多样。不同引擎可以共享物理库、图形抽象、资源工具、脚本运行时和内容格式,再针对自身目标重新组合。

AI 或许会让跨引擎移植、适配和专用模块开发更加容易。但它不能自动替我们决定什么架构值得维护,也不能保证组合起来的系统就会好用。

5最终还是要回到作品

如果现在再让我选择,我依然愿意研究 Rust、Bevy 和自研引擎。它们可以是有价值的技术探索;如果未来某种独特玩法真的要求改变引擎底层,我也不排斥再动手。

但对于当下想做出的沙盒游戏,我更愿意先借助熟悉而成熟的工具,把可以交给通用引擎的部分交出去,只在真正决定体验的地方投入自研。

最近听完 Undertale 音乐会,我又一次被如此简单的像素画面、旋律与故事深深触动。它提醒我:技术复杂度和作品的感染力,并不存在必然的正比关系。

如果目标是学习引擎,那么引擎本身就是作品;如果目标是创造游戏,那么引擎首先应该是工具。

两种追求都没有错。真正需要避免的,是在没有察觉的时候,把「创造游戏的手段」变成了一个永远做不完的目标。

注释

  1. Tuxedo Labs,官方网站。工作室说明其自研工具与引擎,并以体素技术、破坏物理和光线追踪构建 Teardown。 ↩

  2. Bevy,官方介绍及项目主页。说明其 Rust、开源、数据驱动、ECS 和模块化的设计目标。 ↩

  3. Pounce Light,Tiny Glade 技术说明;80 Level,开发者访谈(2024)。开发团队介绍了对 Bevy ECS、调度系统的复用和定制渲染。 ↩

  4. Bevy,Getting Started: Setup。官方介绍开发期动态链接及缩短编译时间的配置。 ↩

  5. Rust Cargo,FAQ: Why is Cargo rebuilding my code? 与 Build Cache。说明依赖特性、构建配置和增量缓存与重新编译之间的关系。 ↩

CONTINUE EXPLORING

沿着这篇文章继续

在地图中查看

On this page