独立游戏提效的真相:从饥荒的“Lua 引擎”说起
——写给还在 Unity 里“一锅乱炖”的独立开发者
本文缘起知乎问答「如何提高独立游戏开发效率?」,原回答里我提了一句“在 Unity/UE 之上再写一层玩法级引擎”。评论区吵得很凶:
“这不就是 RPG Maker 吗?”
“小团队搞编辑器是不是过度工程?”
“饥荒这种体量的游戏是怎么做的?”
于是有了这篇文章——把饥荒拆开,看看到底什么是“玩法引擎”,再给出一条最小可落地的独立游戏提效路线。
1. 先把话说清楚:三层架构模型
层级 | 通俗叫法 | 饥荒里的对应 | 职责 |
---|---|---|---|
L0 系统引擎 | Unity / UE / Godot | C++ 引擎层(Klei 自研 fork) | 渲染、物理、音频、IO |
L1 玩法引擎 | 我们吵了一整楼的那层 | C++ 侧的 Sim + Lua 虚拟机 | 提供对象系统、组件生命周期、热重载、调试器 |
L2 游戏内容 | 策划案 / 配表 / 脚本 | 90 % 的 Lua 脚本(scripts/ 目录) | 角色、物品、季节、AI、剧情、MOD |
一句话:
独立开发者最容易忽视的就是 L1——玩法引擎。
2. 解构饥荒:为什么 90 % 的代码是 Lua 还能稳定跑?
2.1 目录结构速览
dont_starve/
├─ data/ # 美术、音效
├─ scripts/ # ← 90 % 游戏逻辑
│ ├─ prefabs/ # 每个实体一个文件(草、斧头、巨鹿)
│ ├─ components/ # 可复用能力(燃烧、可拾取、烹饪)
│ ├─ brains/ # AI 行为树
│ └─ tuning.lua # 全局数值表
└─ bin/ # C++ 可执行 + LuaJIT
2.2 L1 玩法引擎(Klei 的“Lua 引擎”)提供了什么?
功能 | 饥荒的实现 | 独立游戏可抄的要点 |
---|---|---|
实体-组件系统(ECS) | 每个 prefab 是一个实体,挂任意 AddComponent("combat") | 自己用 ScriptableObject 写 200 行就能跑 |
热重载 | 修改 scripts/prefabs/axe.lua → 游戏内按 Ctrl+R 立即生效 | Unity 用 Addressables + Compile And Run 可 50 % 模拟 |
模块化 AI | Brain = 行为树用 Lua table 写 | 用 NodeCanvas 或自写 100 行 Lua parser 即可 |
调试器 | 内置 c_debug() 控制台 + 可视化碰撞盒 | Unity 用 ImGui + DrawGizmo 一小时搞定 |
MOD API | 直接暴露整个 Lua 环境 | 实际上就是“官方教你用我们的 L1” |
Klei 用 C++ 写了 不到 10 % 的代码,就把“饥荒”这个框架钉死;剩下 90 % 用 Lua 像填表一样做内容。
这,就是“玩法引擎”的威力。
3. 评论区高频质疑统一回应
质疑 | 用饥荒案例回答 |
---|---|
“小团队写引擎是不是过度工程?” | Klei 最早 3 人,先写 Lua 虚拟机 + ECS 花了 4 周,后面 6 年都在填 Lua 内容。ROI = ∞。 |
“RPG Maker 千篇一律” | 饥荒的 Lua 层没有限制你做任何玩法,巨鹿、船难、哈姆雷特全是同一套 L1 长出来的新内容。 |
“策划和程序视角不同” | 饥荒策划眼里的“引擎”就是 tuning.lua 里那张数值表,因为改一行就能让巨人血量翻倍,这就是“自助”。 |
“我没作品空谈架构” | 饥荒第一个可玩 Demo 是 7 天 GameJam 用纯 Lua 写的,验证完才补的 C++ 渲染层。架构先行 ≠ 拖延上线。 |
4. 最小可行路线:从 0 到“自己的饥荒”
以下步骤按 1 人全职、2 个月搭框架、剩下时间填内容为假设。
4.1 第 0 周:玩法原型
- Unity 新建空项目,灰盒一个“砍树→掉木头→做斧头”循环。
- 代码写得越烂越好,只要能跑。
4.2 第 1~2 周:提炼 DSL
- 把“树、斧头、木头”抽象成 3 个 JSON 配置:json
{ "id": "axe", "components": ["weapon", "durability"], "damage": 30 }
- 写个最丑的
RuntimeLoader
,能读 JSON 生成 GameObject 即可。
4.3 第 3~4 周:最小编辑器
- Unity Editor 窗口:
- 左:树形列表显示所有实体
- 右:Inspector 改 JSON 字段
- 按钮:Save & Hot Reload(用
Addressables.Relocate
实现)
- 里程碑:策划无需打开 VSCode,能在 30 秒内新增一把“40 伤害的大斧头”。
4.4 第 5~6 周:组件化
- 把“耐久度、武器、可拾取”写成
MonoBehaviour
,但注册方式用 JSON。 - 目标:代码只增不改,策划通过 JSON 组合出新物品。
4.5 第 7~8 周:Lua 绑定(可选)
- 如果策划不会 JSON,引入 MoonSharp(C# Lua 解析器)。
- 让配置写成 Lua 表,获得“函数级可编程”能力,饥荒同款。
4.6 长期:内容洪水
- 剩下 90 % 时间只做两件事:
- 填 Lua/JSON 表 → 出新实体、新关卡。
- 发现“编辑器不支持” → 回到 C# 扩展 DSL,循环往复。
5. 小结:一句话背下来
“独立游戏开发效率的杠杆点,不是把 Unity 用得多么花哨,而是在第 3 周就搭好自己这款游戏的‘饥荒级 Lua 引擎’——让策划像写 MOD 一样做游戏。”
如果你已经在 Unity 里第三次重写背包系统,是时候停下来,先写一把“斧头编辑器”了。