答:桑比機率完全不用移植,一行都不用改寫成 JS。這正是「表演與判定分離」架構最大的紅利——桑比框架留在 Unity 原地照跑,Web 打中怪物時送 hit_query 過橋問桑比「能不能死」,答案 1~2 幀內回來(模型 A)。機率參數、調整介面、稽核紀錄全部維持你們現有的桑比生態。
唯一要做的新東西:定義「桑比的判定結果 → Web 演出參數」的對照(就是規格書開放問題 1 的 outcome 形式)。
誠實盤點,分三類:
| 類別 | 項目 | 說明 |
|---|---|---|
| 🚫 真做不到 → Unity 殼承接 | 硬體 IO(投幣器/出票機/燈條/串口)、系統級控制(開機自啟、看門狗、關導航列)、精細記憶體管理、原生多執行緒 | 瀏覽器沙盒天生禁止碰硬體——所以架構才設計成 Unity 當機台管家,這些全歸 Unity,已閉環 |
| 💰 做得到但成本高 | 複雜 Shader 工具鏈(沒有 Unity 編輯器生態,要手寫 GLSL)、高階粒子編輯器、大規模骨骼動畫 | 本專案已用「手寫+instancing+烘焙」路線做掉了主要需求;新增華麗特效時成本比 Unity 高,要在需求評審時把關 |
| ✅ 曾疑慮、已實證可行 | 3D 場景+多怪物+特效的整體渲染 | compat 管線已實跑:背景/怪物 instancing/陀螺/地面特效,draw calls 約 30、桌機實測 50+ FPS、載入 3.8 秒 |
剩下的未知數只有一個:板機 GPU 上的實際 FPS——板子到手第一件事實測,配合既有 perfConfig 降級管線調檔位。
兩條產線+一份合約:
時程上 Web 端可先行(橋接層+mock),Unity 端等套件與板子到位做 POC,最後聯調走協定驗收清單。
好消息(查證過 code):引擎端的 Atlas 支援已經存在。專案的 SpriteRenderer 原生支援「同一張 atlas 的所有 sprite 共用一個 draw call」,每個 sprite 可指定 UVRect(在大圖中的子區域)——等同 Unity SpriteAtlas 的 GPU 端效果。缺的只是「打包管線」(把散圖合成大圖+座標表),補上就通:
| 環節 | 做法 | 對應 Unity 概念 |
|---|---|---|
| ① 打包工具 | build 腳本自動跑(free-tex-packer-core 免費可程式化,或整合進現有 asset-intake 工具鏈)。輸入:散圖資料夾;輸出:atlas.webp+atlas.json(每張圖名 → x,y,寬,高) | SpriteAtlas 資產打包 |
| ② 引擎讀取 | 載入 atlas.webp 成一張 texture+讀 json 建 frame 表;建 sprite 時給 texture=atlas, uvRect=frame——SpriteRenderer 現成 API,遊戲邏輯不用改 | Sprite.Create from atlas |
| ③ 分組原則 | 依「同時出現在畫面」分組:UI 一張、道具/投擲物一張、特效碎圖一張;單張上限 2048 | SpriteAtlas 分組 |
| ④ 自動化時機 | npm run build 時自動重打包(美術丟散圖照舊,不用手動操作)+ asset-lint 檢查散圖有沒有漏進 atlas | Build 時自動 pack |
範圍界定(什麼不進 atlas):3D 模型 diffuse(instancing 已批次化,合圖反而搞壞 UV)、全螢幕背景圖(單獨載)、Loading 提示大卡圖。進 atlas 的是:UI 圖示、2D sprite 碎圖、特效序列圖。
已完成:資產瘦身 92%(143→12MB)、開頁預載+真 Loading gate、貼圖 1024 WebP(GPU 記憶體省 75%)、instancing+地面特效烘焙、asset-lint 閘門防退化。
板機階段待做(都已列入路線圖):
__groundFxUploads 穩態必須 0)——專案既有紅線照守先講 Vite 是什麼(用 Unity 對照):Vite 就是網頁界的「Unity Editor+Build Pipeline 二合一」,這個專案從第一天就在用它:
| Vite | 等同 Unity 的 | 說明 |
|---|---|---|
npm run dev | Play Mode | 開發伺服器:瀏覽器即時預覽、存檔自動刷新 |
npm run build | Build 出包 | 把幾百個原始檔編譯+壓縮成 dist/ 成品資料夾(就是要放進 APK 的那包) |
vite.config.ts | ProjectSettings/BuildSettings | 打包規則設定檔 |
.env 檔+mode | Scripting Define Symbols+Build Profile | 下面 Define 三層的第一層 |
Define 設定三層(具體操作):
#if 條件編譯):開一個 .env.machine 檔寫 VITE_MACHINE=1;程式裡寫 if (import.meta.env.VITE_MACHINE);出機台包用 npm run build -- --mode machine——build 時常數被寫死、用不到的分支整段剔除,跟 Unity 的 #if MACHINE_BUILD 同效果。用來切:機台版/開發版/雲端測試版?2d=1/?3d=1/?animjson=1 就是這層——除錯切換用,不用重新 buildinit 訊息下發——嚴禁兩邊各設各的(會漂移對不上)判斷口訣:出包就固定的 → ①;除錯要隨時切的 → ②;操作員會調的 → ③。
原則:一份表、兩邊讀、擁有權分清楚。
DynamicResource/ 的 JSON(Prefab、動畫、關卡)由 Vite 打包載入,這套已在跑待 outcome 形式定案後,哪些表歸哪邊就能列出完整清單。
你的 AssetBundle 直覺完全正確,Web 有等價且更簡單的做法——混合式(建議):
鑲嵌:UniWebView 6(已評估定案:直接包系統 WebView、零額外損耗、v6 主打 Channel Messages 訊息通道、維護最活躍)。全螢幕疊加模式。
資料包裝:上面第 8 題的混合式——dist 資料夾=一包靜態資產,內建出廠版+外置更新版。供檔走 localhost 小伺服器或套件 asset 映射(POC 後二選一,都不需要網路)。
你列的四項正好就是協定規格書的四大塊,全部已定義:
| 你的節點 | 協定對應 | 備註 |
|---|---|---|
| IO 控制訊號 | coin_inserted/pause·resume/hardware_error/payout_result;實體按鍵建議「Unity 統一收再轉發」單軌制 | ⚠️ 按鍵路由待你拍板 |
| 機率控制 | hit_query → 桑比擲骰 → hit_result(模型 A,往返 8~33ms);同幀合併保護 | ⚠️ outcome 形式待定 |
| 遊戲紀錄 | Web 送 round_event 事件流,Unity 記錄+計票(單一真相源);局終對帳、序號防漏 | 已閉環 |
| 錯誤訊息 | 雙向:Web error 上報入 Unity 紀錄;Unity hardware_error 下發凍結畫面;心跳 3 秒斷自動重載+局中回復 | 已閉環 |
共用後台:零影響 ✅。後台對接的一直是 Unity 端(帳務、機率設定、遊戲紀錄),而這些在新架構全部留在 Unity——後台根本感覺不到遊戲畫面換成了 Web。遊戲紀錄由 Unity 依事件流落地,後台照原本方式讀。
操作員選單:功能照舊留 Unity,只有「顯示方式」要二選一(因為疊加式 WebView 蓋在 Unity 畫面上):
pause 凍結)——建議,選單零改動照舊,零改動。桑比框架、彩票機框架的 Scripting Define Symbols 全部維持——Unity 端從頭到尾沒有因為這次架構要改任何 define。唯一新增的是「機台模式」這類要讓 Web 也知道的旗標:由 Unity 經 init 下發(見網頁端第 6 題第三層),不要在兩邊各設一份。