像熱重載程式碼一樣熱重載遊戲設計
大多數引擎交付的是不透明的二進位檔。RakuAI 交付的是你可以比對差異、審查、熱重載的文字——AI 神經系統就在檔案裡直接可定址。正是這個選擇,讓一整個代理團隊能與你並肩打造。
檔案格式週末。在這個引擎裡,AI 是執行環境的基本要素,而不是外掛在旁邊的一項功能。這是我之前就提出過的架構論點。這篇文章要談的,是把它落實的檔案格式。
如果你在大多數引擎上打造遊戲,你交付的產物是一個二進位檔、一個專案套件、一個素材資料庫,或三者的某種組合。你創作的內容存在於專有編輯器之內。你交付的東西對團隊既有的工具而言是不透明的。要比對一個體驗的兩個版本,就得把同一個編輯器打開兩次,然後祈禱變更紀錄是誠實的。
我們走了另一條路。一個 RakuAI 體驗就是一個 .raku 檔案。這個檔案是 JSON。你可以用任何編輯器打開它。你可以在任何程式碼審查工具中比對兩個版本的差異。你可以用結構描述驗證它。你可以在 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_tracking 和 adaptive_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。程式碼審查。差異比對工具。版本控制。Linter。結構描述驗證器。CI 管線。靜態分析。每個平台上的每個編輯器。這些我們一項都不用自己打造。全部免費撿到。
第二:人類讀 JSON 讀得夠好。上面那個檔案不算漂亮,但一位資深設計師不需要受訓就能讀懂。相比之下,一個 DSL 要學一週,才有人能審查 PR。
第三:AI 助理讀 JSON 讀得極好。這一點在 2026 年比三年前重要得多。當設計師請 AI 助理「把魔王調整得更嚇人一點」時,助理可以讀取檔案、提出一個差異變更,然後由人類接受或拒絕這個差異。自訂 DSL 則需要教會每一個助理一套新文法。
代價是真實的。JSON 很冗長。它沒有內嵌數學、註解或簡寫。我們拿表達力換取工具的普及性。到目前為止,這筆交易已經回本了無數次。
這帶來了什麼
一旦你的體驗變成文字,有幾件事會改變。
遊戲設計的 PR 審查。設計師把 target_flow_state 從 0.7 改成 0.5。這個變更在 pull request 中呈現為一行差異。工程與設計一起審查這個變更。PR 中的討論成為「這個體驗為什麼玩起來是這樣」的紀錄。六個月後,當有人問起難度曲線為什麼是這種感覺時,答案就在提交紀錄裡。
體驗的 CI。一個 .raku 檔案沒通過結構描述驗證。建置在變更上線之前就失敗。跑你單元測試的同一套 CI,也跑你的體驗定義。
熱重載。磁碟上的檔案變了。執行環境察覺到了。世界不用重新啟動就更新。開發迴圈縮短到以秒計。
回滾。某個變更弄壞了魔王戰。還原那次提交。體驗就還原了。不用編輯器、不用重建素材、不用長達一週的來回。
由 AI 創作。團隊成員用自然語言描述想要什麼。AI 助理寫出 .raku 的差異變更。人類審查者核准它。這個差異可稽核、可版本控制,並且和任何其他程式碼變更一樣,受同一套審查紀律約束。
這些不是什麼奇特的能力。它們是每個現代軟體團隊對程式庫其餘部分視為理所當然的東西。我們把它們延伸到了遊戲設計。
困難之處
誠實地說說代價。
JSON 沒有註解。我們用附帶的 .md 檔案記錄設計意圖,並用描述性的欄位名稱來補償,但這確實是一種真實的摩擦。
結構描述必須謹慎演進。當世界生成超出原始形態時,我們曾把 schema_version: 1.0 升到 2.0 一次。外面每一個既有檔案都需要一條遷移路徑。這項工作是分內之事,而且並不便宜。
一直想加新欄位的誘惑始終存在。我們抵抗它的力道比聽起來更大。每加一個欄位,就是執行環境必須永久遵守的一條契約。我們的傾向是讓檔案保持精簡,把複雜度放進執行環境,而不是放進檔案。
最後:文字式的體驗定義只有在執行環境真的能用它們做出有趣的事情時才有意義。檔案格式是其底層架構決策的下游產物。如果引擎把 AI 當成內容工廠,這個檔案就只是一份清單。如果引擎把 AI 當成執行環境的基本要素,這個檔案就是樂譜。
如果你想從頭到尾讀完這個格式,結構描述放在公開文件裡,範例檔案隨存放庫一起提供。打開一個看看。把它當程式碼來讀,因為它就是程式碼。
兩天的檔案格式工作入帳。下個週末回到引擎上。
創作你的 AI 能讀能寫的體驗
RakuAI 把 AI 當作執行環境的基本要素,把體驗當作程式碼。打開 .raku 格式、比對差異、熱重載——讓你的助理和你一起在真實世界中打造。