SpinningTop / feat-perf-migration

2D→3D 渲染搬移問題報告

Canvas2D → WebGL 即時 3D(compat 模式)搬移過程的全部問題、根因與修法

日期 2026-07-10(2026-07-13 狀態更新) 記錄 20 項 規範 R1–R16(wiki/conventions) 線上 spinningtop.pages.dev
20問題總數
18已修復並部屬
2排程中/待確認
0未解・追蹤中

核心認知:為什麼會有這批問題

2D 版其實是「離線烘焙的 3D」。烘焙器(Zombie3DRenderer)在載入時把 FBX 模型透過一個調校好的 3D 場景——燈光、材質、相機、頭骨角度、動畫姿勢——逐幀拍成 2D 圖片,遊戲再播放這些圖片。所有「2D 好看」的原因都藏在烘焙器的調校細節裡。

3D 即時管線是照「架構」重寫的新路徑,烘焙器的調校沒有被逐條核對搬移,於是逐項露餡。每一個問題的修法本質都是:把烘焙器的某個調校,正確地重現到即時管線。

批次一・首輪實測

#1–6

部屬後第一輪遊玩發現的 6 個問題。

#1

整個背景全黑

已修復
根因遊戲 canvas 設了不透明(alpha:false),整層蓋住下面的 WebGL 畫面。
修法改為透明(alpha:true),WebGL 3D 層透出來。
#2

怪物太暗

已修復
根因三重:①設定表漏抄烘焙器的「自發光」(5 種怪全漏、狗抄錯值)②第一次修復改在死碼上 ③貼圖漏設各向異性過濾,俯視斜角下被過度模糊變暗。
修法逐型對照烘焙器補齊自發光;man 改用 Lambert 材質;anisotropy=16。
#3

炸彈怪死亡動畫沒演出

已修復
根因血量歸零被標成「不存活」,渲染器第一行就跳過不畫——死亡中的怪整隻消失,動畫進度修得再對也沒用。
修法死亡「演出中」照常渲染;播放進度改用「秒 ÷ 動畫實際長度」對齊烘焙器語義。
#4

撞擊時怪播怪異動作

已修復
根因擊退狀態被誤映射到「死亡動畫」;2D 擊退時根本不切換動作。
修法刪除錯誤映射,擊退維持原動作+身體旋轉。
#5

頭朝向錯(露後腦勺)

已修復
根因烘焙器把頭骨上仰 45° 是在模型旋轉 180° 之後的世界空間套的;即時管線的骨骼在旋轉之前——座標系換算後等效角度是 −45°。第一次照抄 +45° 等於往下低頭,更看不到臉。
修法數學推導共軛換算,改 −45°(蔡實測確認 OK)。
#6

受擊沒閃白

已修復
根因資料鏈斷在源頭——3D 的資料結構根本沒有 flashTimer 欄位;後補的「顏色過曝」又只影響受光部分,蓋不掉自發光,白不徹底。
修法欄位接上+shader 級純白覆蓋(無條件輸出純白,對齊 2D 白剪影)。

批次二・全面盤點

#7–13

agent 全檔掃描 2D 渲染器+烘焙器逐項比對、架構級項目人工二次驗證。

#7

受擊抽動/攻擊/蓄力/挑釁/中獎失敗演出全滅

已修復
根因3D 動畫狀態機只搬了 3 種動畫(走路/死亡/衝刺),2D 支援 4 個維度的演出判定。
修法狀態機重寫,完整對齊 2D 逐型判定(約 150 行)+補載受擊與特殊動畫。
#8

Boss(猩猩)死亡/攻擊動畫壞掉

已修復
根因烘焙器從 3 個 FBX 檔各取動畫;3D 只載走路檔,卻拿其他檔的幀號去切——切到錯的動畫。
修法支援「指定動畫來源檔」,幀號屬於哪個檔就從哪個檔切。
#9

黑殭屍走路=死亡同一段動畫

已修復
根因Monkey.fbx 是「具名動畫」格式,3D 卻對三個動作全切同一段 [0,30]。
修法支援名稱查找(walk/dead/jump_in/intimidate)。
#10

場上物件雙重繪製(效能浪費)

已修復
根因compat 模式下陀螺清單有清空、物件清單忘了清——WebGL 和 Canvas 各畫一次(上層蓋住看不出,純浪費)。
修法物件清單比照清空,一邊只畫一次。
#11

3D 陀螺/空投箱未搬進 WebGL

已修復
修法陀螺(model2)與空投箱皆已由 PropAdapter 即時渲染(含三部件旋轉/傾斜、箱體光暈);後續並修掉陀螺特效層序與寶箱光暈/自發光問題(見特效結案報告續篇)。
更新2026-07-13 補記。
#12

木乃伊/猩猩尺寸疑似縮錯

待實測確認
證據其他怪的烘焙器→3D 縮放換算全部一致(×0.833),只有這兩隻不一樣(×0.4/×0.694)。
下一步實機確認是否明顯偏小,確認後修。
#13

黑殭屍紫色光暈消失

排程中
根因2D 的光暈是套在 2D 身體圖上的;身體改由 WebGL 畫之後,光暈失去載體。
計畫3D 端補紫色光暈(或 Canvas 補畫貼地光圈)。

批次三・實測追加

#14–20

蔡實機遊玩回報的追加問題(含手感層級)。

#14

場邊石頭消失

已修復
根因compat 模式漏接了整個地面裝飾層——石頭、彈射區、警示區、引導箭頭、地面軌跡、尖刺全都沒人畫。
修法地面裝飾層接回 Canvas 疊層(底圖仍由 WebGL 畫),一次全補。
#15

彈射區星星消失

已修復
根因同 #14——星星是彈射區地標,在同一個漏接的裝飾層裡。
修法同 #14 一併回歸。
#16

對決 QTE 介面消失

已修復
根因compat 漏呼叫世界層 UI(drawUIWorld)——對決拉鋸條這批全沒畫。
修法補上呼叫。
#17

怪頭上出現兩個數字、數值還不同

已修復
根因舊渲染器內建的「寫死票數」和機率系統的「水位票數」兩份都在畫。
修法只留機率水位版(正確的業務數字)。
#18

打怪時特效與怪錯位

已修復
根因螢幕震動三層不同步:WebGL 相機有震、Canvas 疊層沒震、地面裝飾自己亂震。
修法三層共用同一份震動數值。
#19

打擊感不足(2D 會「停一拍」再演)

已修復
根因2D 純白剪影期間動畫視覺上是凍住的(hit-stop);3D 被打立即演出,少了那一拍停頓。
修法受擊與死亡都加 0.15 秒動畫凍結,凍完才開始演出。
#20

撞飛時旋風圈仍與怪對不上

已修復
根因確為 3D 模型中心點偏移——怪的邏輯座標與模型視覺中心不重合,canvas 疊層的圈用邏輯座標畫就對不上。
修法特效 3D 化批3a:旋風圈搬進 GroundFx 地板層、以怪的實際座標每幀貼地更新(並套用身體置中偏移),與怪完全同步。詳見特效 3D 化結案報告。
更新2026-07-13 補記。

修錯過的地方

供警惕

這三個失誤都導致「修了但你看沒變」,已寫入規範避免重犯。

改到死碼——亮度第一次修在一支「有被建立、但從未被渲染使用」的舊檔上。 → 規範 R10:改之前先驗證那條路徑真的在跑。
照抄不換算——頭傾斜第一次照抄烘焙器的 +45°,但兩邊座標系差 180° 旋轉,符號要反。 → 規範 R4:空間變換搬移必先推導座標系差異。
修進度、沒修渲染資格——死亡動畫第一次修「播放進度」,但那隻怪根本沒被畫。 → 規範 R9:先確認「有沒有畫」,再修「畫得對不對」。

製作規範 R1–R16

wiki/conventions/webgl-3d-rendering-rules

從 20 項根因提煉,後續所有渲染開發照此走。

規範內容對應問題
R1烘焙器是視覺真相源——任何視覺問題先並排比對,禁止試錯調參全部
R2材質規格逐型對照(材質類型/自發光/各向異性/色彩空間)#2
R3動畫三種來源(幀號/具名/跨檔)+兩種播放語義(停最後幀/循環),一律以秒為源#3 #7 #8 #9
R4空間變換搬移必做座標系換算,禁止照抄數字#5
R5compat 分工邊界:每個視覺元素只能一邊畫,新增必登記#10 #14–17
R6相機/震動三層共用同一份數值#18
R7打擊感標準:受擊/死亡 hit-stop 0.15 秒#19
R8驗收方法:凍結畫面 Canvas2D ↔ Compat 切換逐項對比全部
R9渲染資格與演出分離:血量歸零 ≠ 不渲染#3
R10禁改死碼:動手前先驗證該路徑在跑#2
R11資料鏈完整性:遊戲狀態→映射→渲染逐欄檢查#6