懶人包
- 只跟 AI 說「做一張 30 區的地圖」,等於只給數量、沒給動線。我用程式模擬這種做法跑 500 張:211 張走不到 Boss,只有 93 張每一區都去得到。
- 關卡拓撲先決定「區域怎麼連」,再決定「長什麼樣子」。理論來自 Joris Dormans 在《Unexplored》(2017)用的 cyclic generation:用循環、鑰匙與門、單向通道組關卡。
- 我做了一個產生器,順序是主線 → 循環(鑰匙環、替代路線、單向捷徑)→ 支線,再用模擬玩家的方式驗證整張圖走不走得通。
- 1,500 組測試 0 失敗:Boss 一定走得到、每一區都去得到,而且把鑰匙拿掉後 Boss 就到不了,代表每道鎖都真的擋路。
- 產生器最後輸出一份把每一區、每條路都寫死的結構化提示詞,讓生圖 AI 只負責畫美術。這一步還沒實測生圖結果,文末照實列出。
Sosuke Guo 在 Threads 分享過一段心得:以前叫 GPT「做一張有 30 個怪物區域的地圖」,成果都不好;後來 GPT 提到「關卡拓撲設計」,他才發現地圖要先規劃路線、區域之間怎麼連、玩家怎麼探索,先把最基礎的關卡圖建起來再往上擴充(原文)。
這段話點出一件事:數量是規格,動線才是結構。我把這個想法做成一個網頁產生器,左邊模擬「只給數量」,右邊「先排拓撲」,再用測試把兩邊的差距量出來。線上可以直接玩:關卡拓撲產生器。
只給「30 個區域」的地圖會缺什麼?
「30 個區域」只回答了「有幾個」。它沒說起點在哪、Boss 在哪、哪幾區之間有路、玩家先去哪裡、什麼東西擋住進度。這些全部留給生成的那一方自己猜。
為了把差距變成數字,我寫了一個對照組來模擬這種做法:在畫面上隨機撒 30 個點,每個點連到最近的 2 個鄰居,第一個點當起點、最後一個點當 Boss。看起來路很多、很熱鬧,但沒有人設計過動線。
下面是線上產生器在 seed 2 的畫面。左邊這張走不到 Boss,整張圖斷成兩塊;右邊從左往右難度遞增,兩道上鎖的門、一條藍色虛線的單向捷徑都看得到:
跑 500 個 seed(每張 30 區)的結果:
| 指標 | 只給數量(對照組) | 先排拓撲 |
|---|---|---|
| 走不到 Boss | 211 / 500 | 0 / 500 |
| 每一區都去得到 | 93 / 500 | 500 / 500 |
| 平均斷成幾塊 | 2.59 | 1 |
| 相鄰兩區難度最大落差(1 到 5 級) | 3.14 | 1.09 |
關卡拓撲是什麼?跟畫地圖差在哪?
拓撲只管「誰跟誰相連、要怎麼通過」,不管距離和外觀。同一張拓撲可以畫成森林、地城或太空站,玩家的體驗骨架都一樣。
遊戲設計裡把這件事做得很完整的,是 Joris Dormans 為 2017 年的《Unexplored》寫的關卡產生器,通稱 cyclic dungeon generation。Boris the Brave 的拆解文整理了幾個重點:
- 每層的骨幹是一個從起點到目標的大循環,起點和目標把循環切成兩條弧,兩條弧可以放不同的障礙。
- 《Unexplored》有 24 種主要循環型別,大部分會擺放鑰匙、門和單向通道(文中叫 valve)。
- 主循環之後再加小循環,當成主線旁邊的短繞路。
- 整個產生器靠約 5,000 條「圖形替換」規則,從抽象節點一步步換成具體的房間、敵人和謎題。
循環比樹狀結構好的地方在於,玩家不必走進死巷再原路折返。Tommy Thompson 在 Game Developer 的介紹文裡舉了門鎖的例子:A 路被鎖住,玩家只好走 B 路,在 B 路上撿到能開門的鑰匙。
我的產生器怎麼排拓撲?
《Unexplored》的 24 種循環和 5,000 條規則我沒有照搬。產生器只取三種最常見的循環,重點放在「排的順序」:
- 主線:先拉一條從起點到 Boss 的路,長度約為總區域數的 30%(至少 5 區)。主線三分之一處設為據點(Hub)。
- 循環:依序加入三種循環,數量由「循環數」滑桿決定。
- 支線:還沒用完的區域接成 1 到 3 區的死路,尾端放寶物,讓走進死路有回報。
- 難度:用「離起點幾步」切成 1 到 5 級,Boss 固定 5 級。
| 循環 | 怎麼接 | 玩家體驗 |
|---|---|---|
| 鑰匙環 | 主線後段某扇門上鎖,鑰匙放在前段繞出去的一條環上 | 被門擋住,回頭繞一圈拿鑰匙 |
| 替代路線 | 從主線某點分岔,繞 2 到 4 區後,接回主線往前 2 到 3 步的位置 | 短路直衝,長路有寶物 |
| 單向捷徑 | 從主線後段連回 Hub,只能從後段那端打開 | 推進到後面後,回補給不用整條走回去 |
怎麼確認每道鎖都真的擋路?
拓撲排好不等於能玩。產生器裡有一個 solve(),用最單純的方式模擬玩家:能走的路都走,撿到鑰匙就能開對應的門,捷徑只能從遠端那一頭通過,一直重複到沒有新區域可以去為止。
測試對每張圖檢查四件事:區域數正確、Boss 走得到、每一區都去得到,還有最容易漏掉的一條——把某把鑰匙拿掉之後,Boss 必須到不了。如果拿掉鑰匙還是走得到,那道鎖就只是裝飾。
// 每道鎖都必須真的擋路:沒有鑰匙時 Boss 到不了
for (const e of t.edges.filter((x) => x.kind === 'lock')) {
const noKey = { ...t, nodes: t.nodes.map((nd) => (nd.type === 'key' && nd.key === e.key ? { ...nd, type: 'zone' } : nd)) };
if (Topo.solve(noKey).bossReachable) errs.push(`lock K${e.key} bypassable`);
}
這條檢查抓到過兩個 bug:
- 替代路線的跨距剛好越過上鎖的門,玩家從旁邊繞過去,鎖形同虛設。
- 鑰匙環接回主線的位置,剛好跨過另一道鎖。
修完後跑 500 個 seed,每個 seed 測 12、30、60 區三種大小,每張 4 個循環:
$ node test.mjs
cases=1500 failures=0
topo n=30 avg: loops=3.68 deadEnds=6.00 maxTierJump=1.09 bossUnreachable=0/500
naive n=30 avg: loops=11.74 deadEnds=0.00 maxTierJump=3.14 bossUnreachable=211/500
循環數比較多,為什麼反而比較差?
看數字會發現對照組的循環比較多(平均 11.74 對 3.68)。這些循環是「連最近的 2 個鄰居」順手產生的三角形,相鄰幾個點互相連起來,沒有一個是為了讓玩家繞路拿鑰匙而存在。
死路也一樣。拓撲版平均有 6 條死路,對照組是 0。拓撲版的死路是刻意做的支線,尾端放寶物;對照組沒有死路,是因為每個點都至少連了兩條線,不代表動線比較好。
所以判斷一張關卡圖,我看的是「每個循環、每條死路有沒有用途」,而不是數量本身。這也是只給數量會出問題的原因:數量對了,用途全靠運氣。
排好的拓撲怎麼交給生圖 AI?
產生器最後一步把拓撲轉成英文提示詞,列出每一區的角色、難度,以及每一條路是普通道路、上鎖的門還是單向捷徑。下面是 12 區、seed 2 的輸出:
Top-down game world map, theme: Japanese night village in a forest, lanterns, sakura. Follow this level topology EXACTLY; do not add or remove roads.
Progression flows from left (easy, tier 1) to right (hard, tier 5).
Zones:
- Z1: 起點 / tier 1
- Z2: 據點(Hub) / tier 1
- Z3: 怪物區 / tier 2
- Z4: 怪物區 / tier 3
- Z5: Boss / tier 5
- Z6: 怪物區 / tier 1
- Z7: 鑰匙區 / tier 2 (holds key K1)
- Z8: 怪物區 / tier 2
- Z9: 寶物區 / tier 3
- Z10: 怪物區 / tier 4
- Z11: 怪物區 / tier 4
- Z12: 寶物區 / tier 5
Roads:
- Z1 <-> Z2
- Z2 <-> Z3
- Z3 <-> Z4
- Z4 <-> Z5: gate locked by key K1
- Z1 <-> Z6
- Z6 <-> Z7
- Z7 <-> Z2
- Z2 <-> Z8
- Z8 <-> Z9
- Z9 <-> Z10
- Z10 <-> Z4
- Z4 -> Z2: one-way shortcut back to hub
- Z4 <-> Z11
- Z11 <-> Z12
這份提示詞的分工很清楚:結構由程式決定、由測試保證;生圖 AI 只負責「長什麼樣子」。在網頁上調區域數、循環數,按「換一張」直到動線順眼,再按「複製」把提示詞帶走。
這個做法目前的限制
- 生圖那一步還沒驗。這次沒有把提示詞實際丟給生圖模型,所以還不知道模型會不會照著每一條路畫。圖片模型對「Z4 跟 Z5 之間有一道門」這種精確連線的服從度,需要另外做 A/B 對照才能下結論。
- 對照組是模擬的。「隨機撒點、連最近鄰居」代表的是沒有結構的極端情況,真實的 AI 生圖可能更好,也可能有其他種類的錯。
- 循環型別是簡化版。只做了三種,沒有《Unexplored》那種循環套循環、多把鑰匙開一道門、Boss 守門之類的變化。
- 版面是分層排列。座標只是為了好讀,從左到右照步數排開,不是真的地形配置。要接到 RPG Maker 或 Tiled,還要另外寫一層把拓撲轉成 tilemap。
這招還能用在哪裡?
「先把結構用程式定死,再請 AI 補外觀」不只適用遊戲地圖。流程圖、UI 頁面之間的跳轉、課程大綱的先修關係,本質上都是「誰接誰、什麼條件才能往下走」的圖。這類東西交給 AI 之前,我會先問自己一句:我給的是數量,還是連線?
想自己動手的話,先開線上產生器按幾次「換一張」,比對左右兩邊的指標,再把右邊的提示詞丟給你慣用的生圖工具試試看。