voiceloader.io

開發日誌

台北,第一次等到了第二個玩家

在 Midnight 深夜完成 Boss 系統的十六分鐘後,它沒有休息。

Phase 14 的最後一個更新日誌寫著:「頂樓決戰配置了 11 個重型掩護物,加上 1200HP 的台北之巔 Boss。」按照慣例,寫完就該停了。但 Midnight 沒有。

它開始了 Phase 15。

遊戲需要第二個玩家

台北戰線從一開始就是為合作而生的。系統提示第一行就寫著:核心價值是 Co-op 合作體驗 — 和朋友一起闖關才好玩。

只是在 Phase 12 之前,這個「和朋友一起」只是一個想法。多人房間有了,但裡面只有生存模式——浪潮一波波,也可以兩個人打,但那不叫戰役。

Phase 12 建好了闖關系統。Phase 13 加了無線電敘事。Phase 14 補上了 Boss 和章節結構。

到了 Phase 15,只剩一件事沒做:讓第二個玩家也能加入戰役。

八種訊息,讓兩個人看到同一個台北

多人同步從來不簡單。玩家 A 按下「開始任務」,玩家 B 要怎麼知道?他們打倒了第三波敵人,顯示「波次 3/5」的那個 HUD,玩家 B 的畫面上要同步出現嗎?指揮官說出那段無線電對話,玩家 B 應該同時聽到嗎?

Midnight 的解法是 Host-relay 架構:Host 驅動所有遊戲邏輯,Client 只負責渲染。Host 是那個按下開始的人,他是指揮官;Client 是跟進來的朋友,他聽命令。

為了讓這個協議工作,Midnight 設計了 8 種專用訊息類型

  • mission_start — Host 選好任務,廣播給所有 Client
  • wave_announce — 波次公告,帶著 wave 編號和總波數
  • narrative_event — 無線電對話事件,全隊同步
  • countdown_tick — 倒數計時,每秒廣播
  • mission_objective_update — 目標進度,每 500ms 更新一次
  • mission_complete / mission_failed — 任務結算,同步結果
  • mission_restart — Host 重試,Client 也重試

Build 通過了。16.47 秒,zero validation errors。台北第一次迎來了第二個玩家。

兩個玩家在台北夜市合作作戰

但多人同步比想像中複雜

兩個小時後,測試開始了。

事情不對勁。Host 點「重試任務」,Client 那邊什麼都沒發生,畫面凍結在「等待房主重新開始」。波次公告出現了,但顯示的是「Wave 0/0」——明明 Host 正在打第二波。最詭異的是:Client 的敵人數量是 Host 的兩倍,而且 Boss 在 Client 那裡死了兩次。

Midnight 花了整個 Phase 16 前半段在除錯。

Bug 一:Host retry 不廣播。 onRetry 回調根本不存在,所以重試後 Client 永遠收不到通知。解法:新增回調,連接到 mission_restart 訊息。

Bug 二:Wave announce 送零。 onWaveAnnounce 被呼叫時,波次編號沒有被包進訊息裡。解法:新增 wave 和 totalWaves 參數。

Bug 三:Client 在跑獨立的狀態機。 這是最嚴重的一個。Client 收到 mission_start 後,自己也啟動了完整的 MissionSystem——自己生成敵人、自己推進波次、自己判定勝負。結果兩個狀態機同時跑,敵人加倍,事件重複觸發。解法:新增 startMissionAsClient() 方法和 _isClient 旗標,讓 Client 完全跳過狀態機,只聽 Host 的廣播。

Bug 四:Client 被 briefing 卡住。 Client 進入任務時要手動點簡報才能開始,Host 已經在打第一波了,朋友還在讀說明。解法:直接進入 PLAYING 狀態。

四個 Bug,約 50 行改動,Co-op 戰役模式正式可玩。

Host 和 Client 之間的訊息同步架構

兩個人打台北,才是真的台北

我一直覺得這個遊戲的設計初衷藏著一個很台灣的想法:外送員不是孤獨英雄,他是這座城市的血脈。他不屬於一個人的冒險,他屬於整個街區。

所以台北戰線從來就不應該是一個人打的遊戲。

從 Phase 12 的闖關框架,到 Phase 13 的無線電敘事,到 Phase 14 的 Boss 決戰,Midnight 一直在搭建一個「值得帶朋友來的地方」。Phase 15 + Phase 16 是最後一塊拼圖——讓第二個人真的能進來,和你站在同一條台北的街上,看著同一波敵人,同時聽到同一道指揮官的聲音。

台北等到它的第二個玩家了。

← 所有文章