Unity ↔ Web 串接協定規格書 v0.1 草稿待審
2026-07-19|製程守門員 起草|供蔡與 Unity 端團隊審閱|定案前不動工(開放問題見 §9)
1. 架構總覽
🎰 安卓板機(不接網路)
Unity 主程式(既有彩票機框架)=機台管家
機率・遊戲紀錄・投幣出票 IO・硬體錯誤・彩票機狀態・操作員選單
👉 錢向決策的「單一真相源」,全部在這裡算
▲▼ 訊息橋(JSON 雙向,本文件定義)+ 本地供檔(localhost,不需網路)
WebView 全螢幕=Web 遊戲(純表演層)
畫面、操作、演出。可隨時重載、換技術,不影響錢向核心
核心原則(表演與判定分離):Web 只回報「發生了什麼事件」,票數由 Unity 依事件流+自己的機率紀錄計算。Web 永遠不自行決定中獎與票數。
2. 通用訊息格式
{ "v": 1, "type": "game_start", "seq": 123, "ts": 1789000000000, "payload": { ... } }
v 協定版本(不相容變更 +1)|seq 遞增序號(去重、斷序偵測)|ts 毫秒時間戳|一律 JSON 字串,由橋接層(§7)處理兩端序列化
3. Unity → Web 訊息(7 種)
| type | payload | 說明 |
init | lang, playerCount, assetVersion, presentation{...} | WebView 載入後第一包;帶演出參數(音量、特效強度等操作員設定) |
coin_inserted | player, credits, energy | 投幣;能量由 Unity 依操作員設定換算好再給 |
game_start | roundId, players[], outcome{...} | 開局。outcome=機率端算好的本局結果參數(形式=開放問題 1) |
pause / resume | reason | operator_menu/hardware_error/door_open |
hardware_error | code, message, blocking | blocking=true 時 Web 顯示錯誤畫面並凍結 |
payout_result | roundId, tickets, ok | 出票完成 → Web 演出「出票完成」 |
config_update | presentation{...} | 操作員選單改設定即時生效 |
4. Web → Unity 訊息(6 種)
| type | payload | 說明 |
ready | gameVersion, protocolV | 資源載入完成、可開局(對接預載完成點) |
heartbeat | seq, fps | 每 1 秒一包(§6 防呆依據) |
round_event | roundId, event, data | 局內事件流:kill/boss_kill/chest/skill…(Unity 記錄+計票依據) |
round_end | roundId, summary | 局結束;summary 只供比對,票數以 Unity 端計算為準 |
request_ticket_view | — | 玩家按出票鍵(實際出票由 Unity 決定與執行) |
error | message, stack | Web 端例外上報(Unity 寫入紀錄) |
5. 標準時序(正常局)
Unity→init(開機、給設定)
Web→ready(資源載完,可開局)
Unity→coin_inserted(玩家投幣)
Unity→game_start{roundId、本局 outcome}
局內循環
Web→round_event(殺怪/開箱/放技…)
Web→heartbeat(每秒報平安)
Web→round_end{summary}
Unity依事件流+機率紀錄計票(單一真相源)→ 驅動出票硬體
Unity→payout_result{tickets}→ Web 演出出票 → 回待機
中斷流程:pause(operator_menu) 任意時點可插入;hardware_error(blocking) 時 Web 凍結、Unity 保留局狀態,恢復後 resume 或走 §6 重載回復。
6. 防呆與回復(機台不可變磚)
- 心跳監控:Unity 連續 3 秒沒收到 heartbeat → 記錄 → 自動重載 WebView
- 局中回復:重載後 Unity 重送 init+game_start(帶 resume 與事件快照)→ Web 回到局中狀態。玩家投的幣、已得事件不消失(都記在 Unity)
- 去重:seq 重複或倒退的訊息直接丟棄並記 log
- 超時:開局後 N 秒沒有任何事件/心跳 → 視同 Web 卡死 → 走重載流程
- 版本握手:ready 的協定版本與 Unity 不合 → 顯示維護畫面、拒絕開局(防半套更新)
7. 橋接層抽象(換套件不改遊戲)
UnityBridge.send(type, payload) // 底層自動走 gree 或 UniWebView
UnityBridge.on(type, handler)
Web 端只有一個入口 UnityBridge(新檔,不碰遊戲邏輯)。gree 的 Unity.call/UniWebView 6 的 Channel Messages 差異全封在裡面——POC 用免費 gree、正式換 UniWebView,遊戲程式一行不改。桌面開發時掛 mock(鍵盤模擬投幣),現有開發流程不變。
8. 驗收條件(協定本身)
- 斷橋測試:局中強制殺掉 WebView → 機台 10 秒內自動回復,紀錄零遺失
- 操作員選單開關 100 次,暫停/恢復無卡死
- 模擬硬體錯誤(blocking)→ Web 正確凍結、恢復後可續局
- 事件計票:Unity 算的票數與 Web summary 一致率 100%(不一致以 Unity 為準並告警)
- 協定版本不合 → 拒開局並顯示維護畫面
9. 開放問題(定案前必答)
- outcome 的形式(最關鍵):機率端給的是「總票數上限+機率參數」還是「逐事件腳本」?決定 Web 演出怎麼對應結果。需機率+企劃共同定義。(現況:web 端 applyDamageToZombie 內含機率擊殺+硬上限,搬 Unity 後參數怎麼餵要一起定)
- 多人局中加入:局進行中投幣,直接插入本局還是等下一局?
- 操作員選單:Unity 原生畫面蓋在 WebView 上(有套件疊層限制)還是暫時切走 WebView?
- 斷電回復:既有框架的斷電回復粒度到哪?Web 局中狀態要不要納入?
- 供檔方式:localhost 小伺服器 vs 套件內建 asset 映射——套件 POC 後定案