↓ 快轉到主要內容

為單機遊戲打造自主 AI Agent 為何走向結構性潰敗?GK2 自主遊戲 Agent 專案復盤

·2855 字·6 分鐘
Y Cheung
作者
Y Cheung
Blogger, Programer & Traveler.
目錄

一、 事實:107 個版本到底換來了什麼?
#

在 PLAN.md 最初的藍圖中,這是一個預估 2.5 至 3 週、由輕量決策模型驅動、能夠在遊戲中自主運轉的新一代 Agent。

然而,當版本號推進到 v0.9.107 時,實機的真實數據為我們展現了一場投入與產出的極度失衡:

實機真正做到的(Verified Baseline):

  • 房門全自主進出(遊戲門解析 -> 按E(指名門) -> ok:door_opened)。
  • 自主從起點走到村莊。
  • 完成了僅僅一條任務記錄:[Quest] completed 25_village_watchmen_2。
  • 模擬 E 鍵成功觸發特定 NPC 劇情對話。
  • 完成了底層資料傾印:產出 world.json、tech.json、defs.json、quest_table.json(549 條)與 zone_graph.json(3025 節點)。
  • 409 條單元測試全數通過(0 Warning, 0 Error)。

承諾卻從未達成的(The Missed Core):

  • M7 任務鏈:「自主完成 \(\ge 1\) 條主線任務」從未達成。
  • M8 對話:answer: 執行器實機呼叫次數為 0。
  • 合成鏈:全量日誌中,crafted 關鍵字命中次數為 0。
  • 實機狀態:在 §9.1 規劃的狀態矩陣中,絕大多數項目永遠停留在 🟡「已寫代碼,未實機測」,標註為 ✅ 的只有寥寥數行。

結論直白且殘酷:我們寫了 107 個版本,覆蓋了 400 多條單元測試,但真正通過實機端到端閉環驗證的能力,不到 5 項。專案留下的唯一真資產,只有逆向遊戲 API 和資料結構傾印的副產品。

二、 根因剖析:七個連環結構性陷阱
#

投入與產出的巨大脫節不是因為編碼速度慢,而是架構決策與工程推進策略陷入了系統性的負反饋陷阱。

  1. 前提未立,大廈先起:導航阻塞引發的骨牌效應

遊戲內任務 NPC、工作台和作物,普遍分佈在需要區域 streaming 載入的動態地圖中。但在 Unity IL 反編譯資料中,底層根本沒有跨 scene 的靜態 transit 連接邊。

這意味著「走得到目標」這一基礎假設在底層是斷裂的。

自建導航(A* + 接力跳點 + 脫困補償)從 v0.9.24 一路修補到 v0.9.107,期間不斷在對抗隱形牆、地圖穿模下沉、門鎖狀態與不可達網格。當前置條件「走到 NPC 面前」不成立時,依賴其存在的所有上層模組——任務觸發、對話決策、材料製作——全部被懸空,無法在實機上得到驗證。

代價代碼化:應該在第一週進行的最核心尖兵測試「遊戲自帶的尋路是否能跨區直調?」被略過,導致整個專案一直都在給一個不可靠的地基打補丁。

  1. 在鬆散假設上立項,現實推翻後拒絕剪枝

專案啟動時寫了 M0 至 M15 龐大的里程碑矩陣。

  • §1 原定決策週期為 500ms,在實機環境中立刻被推翻,被迫放寬至 3000ms(模型超時 9000ms)。
  • 在 §8.4 中,團隊已明確標記:「能力擴張只是在院子裡多幾種空轉方式,M11–M14 必須擱置到自主進村達成後。」
  • 但到了 §9,規劃卻再度失控,全面平鋪展開墓園、農耕、教堂、工人、戰鬥等四個批次。

目標從「完成第一個閉環」漂移為「把整座遊戲的所有玩法全部用架構包進去」,在現實邊界已經收緊時,依然沒有壯士斷腕砍掉外圍範圍。

  1. 「AI」幻覺:承擔了雙重複雜度,貢獻接近於零

我們在架構中引進了 OpenJev / Ollama 本地模型(nimble),期待它能依據場景自主推理下一步行為。 然而在真實實機中:

  • nimble 的決策置信度長期在 0.25–0.35 徘徊,遠低於預設的 0.5 閾值,最後只能妥協降閥門。
  • 實際驅動角色行為的,全是由手寫的 IChoiceFilter、冷卻黑名單、強制注入規則與 Fallback 分支。

系統因此承受了最壞的局面:既要維護非同步 LLM 佇列、請求逾時、重試退避、過期決策廢棄等高維分散式複雜性;實際在做決策的,卻依然是另一套手寫規則。用規則做底層決策,反而比用純腳本更重、更難調試。

  1. 反饋迴圈過長,完全依賴人工排查

一個健壯系統的迭代速度取決於反饋迴圈的秒級閉環。而在這個專案中,一次驗證需要:

1編譯部署 -> 起 Ollama -> 腳本保溫 -> 開啟遊戲 -> 載入存檔 -> 人工盯跑數分鐘 -> 提取日誌 -> 分析十萬行 Log

尤有甚者,單元測試中的 409 條測例全部是純記憶體資料邏輯測試。而專案中 90% 以上的致命 Bug——如 v0.9.13 的反射死代碼、v0.9.14 的狀態乒乓、v0.9.23 的「幻影最佳距離」——全發生在遊戲反射呼叫、物理穿模與引擎執行緒生命週期中。單元測試完全處於盲區,逼得工程師只能「靠猜寫碼,靠命驗收」。

  1. 「先全寫完再 DEBUG」對技術負債的指數級放大

在 §9 中採取的折衷裁決是:「先把 PLAN 的功能分批寫完,最後再集中除錯。」 這一決策在複雜整合系統中是毀滅性的。

專案真正的瓶頸從來不是「代碼量不夠」,而是「未驗證的假設過密」。當 tech:(科技解鎖)、build:(建築佈局)、EarnSpheres(光球採集)和 DevGoals(發展目標)全部帶著 🟡 標記上線且彼此相依時,一旦系統在實機中停擺,定位錯誤的維度呈指數級膨脹,根本無從判斷究竟是尋路失敗、UI 模態窗凍結,還是狀態機死鎖。

  1. 核心架構約束反覆自我踐踏

專案初期立下了諸多設計軍規,但隨著實機阻塞,規則開始反覆自我打架:

  • §6.3 承諾「不模擬鍵盤,直接呼叫遊戲底層 API」,但在 v0.9.79 為了解決劇情卡死,妥協寫入虛擬 E 鍵連擊。
  • 承諾「嚴格禁止任意 Teleport,只允許在 transit 點 \(\le 3\text{m}\) 內傳送」,但在 v0.9.82 的門解析(Door-Jump)中,依然發生了把玩家傳送到地圖外 (-1000, ..) 虛空中的惡性事故。

每一次破壞原則的「特事特辦」,都讓圍繞舊原則建立的狀態過濾、超時判定和看門狗機制隨之作廢,引發更多不可預測的次生 Bug。

  1. 形式化文檔與同步摩擦

專案內維持著極度繁重的周邊資產維護:

  • workshop/filters/ 與遊戲外掛目錄 src/ 採用了雙份同步設計,每次提交都強制要求 SHA-256 哈希複核。
  • PLAN.md 膨脹至數百行,外加 scan/、GameApiMap、Filters、History 等十幾份文件。

當系統核心迭代停滯、基礎功能尚不閉環時,過度沉重的文檔與同步機制並未帶來清晰度,反而成為吞噬心智與開發動力的無效摩擦。

三、 經驗教訓
#

這 107 個版本雖然投入遠超產出,但也給 Y CHEUNG 後續類似的遊戲 AI / 自動化 MOD 開發提供一些經驗:

  1. 先測底層前置依賴,不要先寫業務功能:若系統依賴「能走到 NPC 面前」,那麼第一步的全部精力就該放在「能否穩定從 A 走到 B」。尋路和地圖串接沒有結論前,任務、對話和製作邏輯寫得再多也無法驗收。

  2. 先用純規則跑通閉環,再考慮接模型:控制流、物理交互和狀態機還不穩定時,引入 LLM 只會讓問題變得更渾濁。應該先用純代碼腳本把最小閉環跑順,確認決策邊界後,再考慮是否需要模型接手。

  3. 測試要盡早貼近實機環境,而非只寫離線單元測試:400 多條純記憶體邏輯測試全綠,無法保證外掛在遊戲引擎生命週期裡不崩潰。在反編譯與外掛開發中,失敗往往都在反射呼叫與物理交互,測試環境必須盡可能早地覆蓋真實邊界。

  4. 堅持逐個驗證假設,避免批量堆積代碼:「先分批寫完、最後集中除錯」在多模組耦合的專案中風險極高。每一個動作原語(開門、尋路、對話、製作)都該具備獨立日誌與閉環驗收標準,驗過一項再推下一項,避免依賴鏈斷裂導致無法排查。

  5. 謹慎權衡架構妥協的連鎖反應:中途打破「不模擬按鍵」或「不任意傳送」的約定,往往只是把局部問題轉移成了更隱蔽的全域性 Bug。若初期架構承諾難以維持,應正式重估技術方案,而非在原架構上反覆追加特例補丁。

相關文章

Pokemon Pokopia 喜歡的東西

·516 字·2 分鐘
Pokémon Pokopia 中喜好完全一致的寶可夢群組大部分都是同一進化鏈,也有比較特別的是跨族相同的情況:水箭龜&黏美龍、拉普拉斯&水君這類組合。以下列出喜好相同的寶可夢供大家參考。在Y CHEUNG 做的 Pokémon Pokopia 寶可夢圖鑒 網站中也可以在寶可夢詳情popup中直接看到擁有相同喜好的寶可夢是誰。