系列: 与 AI 一起学编程

像代码一样热重载游戏设计

Experiences as code:一种可 diff 的 JSON 格式,带有运行时 AI 钩子。

Experiences as Code One .raku file, every tool you already own { "schema_version": "1.0", "ai": { "dda_enabled": true, "target_flow_state": 0.7 } } PR review CI validation Hot reload Runtime AI nervous system, every frame
文件是乐谱,运行时是乐团。

大多数引擎发布的是不透明的二进制文件。RakuAI 发布的是可以 diff、可以评审、可以热重载的文本——AI 神经系统就在文件里,随时可以寻址。正是这个选择,让一整个由智能体组成的团队能够和你一起构建。

文件格式的周末。在这个引擎里,AI 是一个运行时原语,而不是附加在旁边的功能。这是我此前一直在阐述的架构主张。这篇文章要讲的是让这个主张变得具体的那个文件格式。

如果你在大多数引擎上做游戏,你交付的产物是一个二进制文件、一个项目包、一个资产数据库,或者三者的某种组合。你所编写的内容存在于一个专有编辑器内部。你交付的东西对你团队已经在用的工具来说是不透明的。想要 diff 两个版本的体验,意味着要把同一个编辑器打开两次,还得祈祷变更日志是诚实的。

我们走了另一条路。一个 RakuAI 体验就是一个 .raku 文件。这个文件就是 JSON。你可以在任何编辑器里打开它。你可以在任何代码评审工具里 diff 两个版本。你可以用模式(schema)校验它。你可以用 git 对它做版本管理。你可以在 PR 里评审它。你可以热重载它。如果你愿意,你甚至可以手写一个体验文件。

这个文件格式并不炫目,但它是承重的。

一个真实的 .raku 文件长什么样

下面是一个真实的游戏定义,为本文做了裁剪:

{
  "schema_version": "1.0",
  "game": {
    "title": "My Space Shooter",
    "genre": "space_shooter",
    "template": "space_shooter",
    "mode": "prototype",
    "max_players": 1
  },
  "ai": {
    "dda_enabled": true,
    "target_flow_state": 0.7,
    "profiler_mode": "active",
    "emotional_tracking": true,
    "adaptive_music": true
  },
  "entities": [
    {
      "type": "player_ship",
      "health": 100,
      "shield": 80,
      "speed": 22.0,
      "fire_rate": 0.09
    },
    {
      "type": "enemy_wave",
      "count": 8,
      "health": 15,
      "ai_behavior": "strafe",
      "properties": { "enemy_id": "interceptor" }
    },
    {
      "type": "boss",
      "health": 500,
      "ai_behavior": "boss_pattern"
    }
  ]
}

这就是一个体验的大部分内容了。一个带模式版本的头部。一个包含表层元数据的 game 区块。一个配置运行时 AI 的 ai 区块。一个描述世界中有什么、每个实体如何行为的 entities 数组。

有几点值得单独指出。

ai 区块就是运行时契约

再看一下这部分:

"ai": {
  "dda_enabled": true,
  "target_flow_state": 0.7,
  "profiler_mode": "active",
  "emotional_tracking": true,
  "adaptive_music": true
}

这里就是文件宣布「AI 神经系统已开启」的地方。不是「让 GPT 帮我写一个关卡」,而是开启——在运行时层面,每一帧,伴随玩家游玩的全过程。

dda_enabled 开启动态难度调整。运行时会分析玩家正在做什么,并即时重塑遭遇战。target_flow_state: 0.7 是运行时所瞄准的难度区间。profiler_mode: "active" 表示 AI 在读取玩家的行为,而不只是采样它。emotional_trackingadaptive_music 是同样的思路应用到其他子系统上。

一个工厂模式的引擎不可能在文件层面拥有这些旋钮,因为没有运行时 AI 可供文件寻址。在我们的引擎里,这些旋钮就是作者告诉神经系统「这应该是一种什么样的体验」的方式。

你可以在 PR 里评审这个区块。你可以在 CI 里对两个数值做 A/B 测试。一个从未见过编辑器的制作人也能读懂这段内容,并就「目标心流状态」意味着什么与工程团队展开对话。文件格式让设计决策变得可见。

逐实体的 AI 行为是一个字符串,而不是一次集成

文件中的每个实体都可以携带一个 ai_behavior 字段:

{
  "type": "enemy_wave",
  "count": 8,
  "ai_behavior": "strafe"
}

"strafe" 不是一次模型调用,而是运行时中一个已注册的行为,由神经系统层驱动。同一个实体可以是 "patrol",可以是 "boss_pattern",也可以是运行时懂得执行的任何其他行为。文件不会导入一个模型,它寻址的是一种能力。

这就是如何将文件格式与特定模型解耦的方法。作者写下意图,运行时决定用哪个模型、哪套权重、哪种确定性兜底方案来实现这个意图。下个季度换掉模型,.raku 文件不需要改动。

这种分离比听上去更重要。我接触过的每一个把某个特定 LLM 硬编码进引擎的团队,都在模型厂商变动时不得不重做整个集成。我们不需要。

为什么是 JSON

这是我展示这个文件格式时被问得最多的问题。为什么是 JSON,而不是一种拥有更友好数学表达式语法、内联脚本和响应式绑定的自定义 DSL?

三个原因。

第一:每个工具都已经会说 JSON。 代码评审、diff 工具、版本控制、代码检查工具(linter)、模式校验器、CI 流水线、静态分析、每个平台上的每个编辑器——我们不需要自己造这些东西,直接免费拿来用就行。

第二:人类阅读 JSON 的能力足够好。 上面那个文件并不好看,但一位资深设计师无需培训就能读懂它。相比之下,一门需要花一周时间学习才能让人参与 PR 评审的 DSL 就差远了。

第三:AI 助手对 JSON 的阅读能力极强。 这一点在 2026 年的分量比三年前重得多。当一位设计师要求 AI 助手「把这个 boss 调得更吓人一点」时,助手可以读取文件、提出一个 diff,人类再决定接受还是拒绝这个 diff。换成自定义 DSL,就得教会每一个助手一套新的语法。

代价是真实存在的。JSON 很啰嗦,没有内联数学表达式、没有注释、没有简写。我们用表达力换取了工具生态的普适性。到目前为止,这笔交易已经多次回本。

这带来了什么

一旦你的体验变成文本,一些事情就变了。

游戏设计的 PR 评审。 一位设计师把 target_flow_state 从 0.7 改成 0.5,这个改动会以一行 diff 的形式出现在一个 pull request 里。工程和设计一起评审这个改动。PR 里的讨论就是「这个体验为什么是这样玩的」的记录。六个月后,当有人问起为什么难度曲线是这个感觉时,答案就在提交日志里。

体验的 CI。 一个 .raku 文件没通过模式校验,构建就会在改动上线前失败。跑你单元测试的那套 CI,也跑你的体验定义。

热重载。 文件在磁盘上发生变化,运行时会注意到,世界随之更新,不需要重启。开发循环缩短到几秒钟。

回滚。 某个改动破坏了 boss 战,回退那次提交,体验就跟着回退了。不需要编辑器,不需要重建资产,不需要一周的往返。

由 AI 撰写。 团队成员用自然语言描述他们想要什么,AI 助手写出 .raku 的 diff,人类评审者批准它。这个 diff 是可审计、可版本化的,并且遵循和其他任何代码改动一样的评审纪律。

这些都不是什么稀奇的能力。它们是每个现代软件团队在代码库其余部分早已习以为常的东西。我们把它们延伸到了游戏设计上。

难的地方在哪

诚实地说说代价。

JSON 没有注释。我们用配套的 .md 文件记录设计意图、用描述性的字段名来弥补,但这仍然是一个真实的摩擦点。

模式(schema)的演进必须小心翼翼。我们曾经从 schema_version: 1.0 升到 2.0,因为世界生成的需求超出了原有的形状。所有已经在外面流通的文件都需要一条迁移路径。这份工作是分内之事,而且并不轻松。

总有一种想不断添加字段的冲动,我们比听上去更用力地在抵制它。每加一个字段,就是运行时要永久兑现的一份契约。我们的倾向是让文件保持精简,把复杂性放进运行时,而不是塞进文件里。

最后一点:基于文本的体验定义,只有在运行时真的能用它们做出有意思的事情时才有意义。文件格式是下游产物,上游是那个更根本的架构决定。如果引擎把 AI 当作内容工厂,文件就只是一份清单。如果引擎把 AI 当作运行时原语,文件就是乐谱。

如果你想从头到尾读一遍这个格式,模式定义在公开文档里,示例文件也随仓库一起发布。打开一个看看,把它当作代码来读,因为它本来就是代码。

两天的文件格式工作已经收工。下个周末回到引擎本体。

编写你的 AI 能读写的体验

RakuAI 把 AI 当作运行时原语,把体验当作代码。打开 .raku 格式,diff 它,热重载它——让你的助手和你一起在真实世界中构建。

← 所有文章