有些作品從功能清單開始,有些作品則是先從一個畫面開始。這次的「逛夜市」就是後者:我先想像一條有中文招牌、攤販燈光和老街建築的台灣夜市,再請 GPT 6 Astra 協助把它一步一步變成可以在瀏覽器裡走進去的 3D 世界。
這篇文章記錄整個過程。GPT 6 Astra 在這個專案裡的推理等級全程使用 medium,工作分成兩條線:用 Blender 建立與整理場景資產,再用 Three.js、TypeScript 和 Vite 把模型變成可操作的網頁漫遊體驗。
現在可以直接開啟 「逛夜市」Demo。桌面版使用 WASD 或方向鍵移動、滑鼠環顧,手機版則提供虛擬搖桿與拖曳視角。
一、先把「想做的夜市」說清楚
第一個提示詞沒有急著談程式,而是先描述作品的氣質:以台灣夜市為背景、帶有 2000 年代遊戲的復古低多邊形風格,同時保留真實台灣夜市的招牌、攤位和街道尺度。最初的想像甚至包含冒險與戰鬥,但實作時先把環境本身做好,讓「走進去」成為第一個可驗證的目標。
二、先做一塊街區,再擴成完整夜市
第一版先驗證一小塊可讀的街景:約 3 × 2 個街區、36 棟建築、24 種攤販與 20 台販賣機。這一步的重點不是數量,而是確認道路、入口和建築的比例能不能支撐後續的第一人稱視角。
當場景從一張渲染圖變成可以被走進去的空間,留出中央道路與入口就很重要。畫面可以塞滿物件,但玩家不能一開始就被攤位或建築堵住。
三、用密度讓夜市看起來像夜市
有了基本街區後,下一個問題是「夜市的熱鬧感從哪裡來?」答案不只是把模型數量加大,而是讓攤位沿著道路形成有節奏的密度。新增不同的小吃攤、外圍建築、住宅、公寓、公共設施與老街建物,並在街區四周保留道路和店面入口。
這一輪把規模推到約 140 × 126 公尺,攤販增加到 58 座,並用不同高度、屋頂和立面,讓俯視時不再像幾個重複的方塊。
四、同一條街,不能長得像複製貼上
生成場景很容易先得到「數量」,卻不一定得到「地方感」。當街上的建築重複率太高,玩家走幾步就會失去方向,也會覺得整個夜市只是同一棟房子被複製了很多次。
因此這一輪把建築當成一組組有個性的街景角色:保留榕安大旅社作為七層地標,再調整每棟建築的樓層、窗型、陽台、屋頂、招牌文字、色系與牆面材質。原本的攤販、販賣機和道路配置則維持不變,避免為了增加變化而破壞已經能走的路線。
五、讓攤位熱區有自己的節奏
下一個調整是把「平均分布」改成比較像真實逛夜市的節奏:北側道路形成兩側緊密相連的攤販熱區,其它街段保留疏密不同的段落。攤位最後來到 116 座、46 種類型;販賣機則用三台、兩台和獨立機台組成幾個小群組,不把它們均勻散落在每個角落。
路燈也從道路中央移到路邊,燈臂和照射方向朝向街道中心。這類小調整不一定會出現在一張總覽圖裡,卻會直接影響玩家在第一人稱視角下感受到的道路尺度與光線方向。
六、從 Blender 模型變成可以走的網頁世界
場景穩定後,工作重心從 Blender 移到 Three.js。這不是單純把 GLB 放到網頁上,而是要替它補上「玩家如何進入、如何移動、如何知道自己在哪裡」這些互動層。
- 場景載入:以 Vite 載入 GLB、建築資料、攤位配置與碰撞框。
- 第一人稱視角:桌面支援滑鼠環顧,瀏覽器不允許 Pointer Lock 時提供拖曳替代方案。
- 移動與碰撞:使用匯出的物件碰撞框、空間索引和小步進,讓玩家沿著障礙物滑行而不是穿牆。
- 介面與回饋:加入載入進度、暫停、重置入口、小地圖、畫質與音量設定。
- 環境聲音:使用台北市場的免費實地錄音,依所在街區做簡單混音,讓不同位置有不同的夜市氛圍。
七、先把角色加入流程,而不是一次做完所有系統
從這裡開始,提示詞也變成一種工作分界。Blender 負責模型、骨架、材質與動畫;網站程式負責載入、碰撞、路線、互動與狀態。先把兩邊的責任分清楚,再用小批次循環,比一開始就同時做角色、車輛、交易和戰鬥更容易驗證。
同一輪也處理了產品表面:中文標題改成「逛夜市」,英文標題是「SAY YACHI」,並讓全區光源在進入前就準備完成。名稱、語言與燈光不是獨立的裝飾,它們會影響使用者第一次看到入口時,是否能理解這個作品要帶他去哪裡。
八、角色不是貼上去,而是要走得像人在逛
第一批角色先做四種:兩位路人、兩位攤販或店家工作人員。路人需要有骨架、走路、停下來看攤位再繼續前進;工作人員則留在攤位或店家附近招呼,偶爾小範圍移動,但不能走出自己的工作位置。
這個順序很實際:先驗證一個人能不能正確載入、走路、停看,以及能不能和玩家互相碰撞,再擴大角色造型與人數。否則一次加入大量人物後,問題會很難判斷究竟來自模型、動畫、行為還是碰撞。
九、用人群把夜市從場景變成地方
小批次驗證通過後,才把人群擴大:新增 30 種路人造型,涵蓋大人、學生、孩童與長輩;再增加五種走路狀態,讓腳步、膝蓋彎曲、擺臂和速度不會全部一模一樣。工作人員也增加不同服裝與角色類型,分配到攤販、店家和服務據點。
目前場景共有 44 種原創低多邊形人物設計、102 位逛街路人和 154 位攤販與店家工作人員。這些數字的意義不只是「場上有很多人」,而是每個人都必須在可接受的更新成本下持續行動,並且不能堵住玩家的主要路線。
十、最後的微調:腳步、天空與瀏覽器裡的感覺
最後一輪很像打磨遊戲手感。先修正路人的膝蓋彎曲方向,確保腿部動作看起來是向前走;再替天空加上少量星星、雲和月亮,讓玩家抬頭時不會只看到一片平色背景。
這些變更都必須同步更新 Blender 原始資產與網頁版 GLB,然後重新做骨架測試、場景載入、碰撞、桌面與手機版瀏覽器檢查。只有在靜態畫面好看,還不代表第一人稱漫遊真的舒服。
這次的工作方式:AI 是方向盤,迭代才是引擎
這個專案讓我更清楚看到,AI 協作最有價值的地方不只是「幫忙寫一段程式」,而是能在不同尺度之間來回切換:一方面討論夜市應該有什麼樣的街景,另一方面又能落到碰撞半徑、GLB 匯出、載入流程和測試案例。
| 階段 | Blender/資產側 | Three.js/網站側 |
|---|---|---|
| 環境 | 建築、攤位、招牌、燈具與場景比例 | GLB 載入、材質轉換、固定光照與相機 |
| 可行走空間 | 保留道路、入口與物件位置 | 碰撞框、空間索引、移動與滑行 |
| 人群 | 角色造型、骨架與走路動畫 | 路線、停看行為、工作範圍與玩家碰撞 |
| 體驗 | 天空、燈光方向與視覺層次 | 響應式控制、小地圖、音效與畫質設定 |
每次只推進一個可以驗證的批次,讓畫面、資料、程式與測試一起前進,這比追求一次生成「完整遊戲」更可靠。這也是 medium 推理等級在這個專案裡的實際節奏:由人決定方向與取捨,讓 AI 協助拆解、實作、檢查,再根據瀏覽器裡真正看見的結果繼續修正。
目前完成了什麼?
「逛夜市/SAY YACHI」現在是一個以復古台灣夜市為主題的第一人稱網頁漫遊 Demo,包含六個街區、58 棟不同建築、116 個攤位、20 台販賣機、全區固定照明,以及 44 種人物設計組成的路人與工作人員人群。玩家可以在桌面或手機瀏覽器裡探索,切換繁體中文與 English,調整環境音和畫面品質,也能用小地圖確認自己所在的位置。
它目前仍然是一段漫遊體驗:購物是情境動畫,尚未加入實際交易、跳躍或戰鬥。保留這個界線,反而讓作品的核心更清楚——先把「走進一個有地方感的台灣夜市」做好。
從一句提示詞到一條可以走的街,真正重要的不是一次生成完成,而是每一輪都能看見、測試並修正。