材質表¶
本檔角色:全 31 種材質的權威 source of truth。 程式端執行 source of truth:
src/material-params/materials.ts(必須與本檔一致;PR review 強制同步)。
1. 欄位定義¶
| 欄位 | 單位 / 型別 | 說明 |
|---|---|---|
name |
中文名 | UI 顯示名稱 |
id |
string | 程式識別符(snake_case) |
desc |
string | 玩法定位 / 用途 |
forbidden_scopes |
vehicle / environment |
禁止用於哪類 GLB;空白 = 任意 |
allowed_part_types |
chassis / body / tire / motor / battery / roller / chip / weapon |
白名單例外(在 forbidden_scopes 內仍允許) |
density |
g/cm³ | 密度 |
yield_strength |
MPa | null |
屈服強度(材料強度數值,與「能否破壞」無關,破壞由建模決定,見 §10) |
ultimate_strength |
MPa | null |
極限強度(同上) |
friction |
0–3 | 摩擦係數 |
restitution |
0–1 | 彈性係數 |
thermal_conductivity |
W/(m·K) | null |
熱導;null = 不參與熱傳合成 |
specific_heat |
J/(kg·K) | null |
比熱;null = 同上 |
thermal_limit |
°C | null |
過熱閾值(材料軟化/熔點溫度數值,與「能否熱壞」無關,由建模決定,見 §10);null = 該材質未定義有意義的熔點(地表抽象材質、fluid sensor mode) |
magnetism_role |
enum:passive / source / none |
磁性身分(三選一,型別系統強制互斥)。passive = 被動鐵磁、source = 主動磁源身分、none = 無磁性(多數材質)。詳見 §8 |
magnetic_susceptibility |
0–1 | null |
被動鐵磁強度(材料固有屬性、電子組態決定的磁化率);僅 magnetism_role: passive 時有值,其他 role 為 null(markdown 表記 —)。主動磁源強度由建模層 Root Extras magnet_source_strength_n 決定(見 §8.2) |
rolling_resistance |
基準 1.0 | 車輛行駛該地面的滾動阻力(所有材質必填,作為 fallback 防護避免疏忽放錯位置造成 runtime 運算問題) |
is_fluid |
bool | 觸發 sensor mode + deploy_behavior |
deploy_behavior |
enum | 5 種:grip_loss / sticky / freeze / burn / corrosive |
deploy_params |
object | deploy_behavior 對應參數 |
display_order |
{ vehicle?: number, environment?: number } |
可選;UI 排序覆蓋值(小到大),無設則用 §2 表格 array index |
命名分層:
- 程式(
materials.ts):以id為唯一識別符;不存name/desc - 本檔規格:
id+name(繁體中文)並存,做為設計討論與 PR 同步基準 - UI 顯示:i18n bundle 對
id取name+desc的繁中 / 英文 / 其他語言;UI 不直接讀本檔name/desc - i18n 鍵契約:每個 canonical id 必須在所有支援語系提供
materials.<id>.name與materials.<id>.description;完整性測試以materials.ts清單逐一驗證,禁止只有部分語系或部分材質有值 - 共用顯示格式:編輯器主材質、子網格覆寫、場地 entity 與含合法
{material}參數的驗證訊息,統一顯示<本地化名稱> (<canonical id>) — <本地化用途>;表單實際值及 canonical 資料仍只使用id。未知 id 不猜測翻譯,驗證訊息保留原值以利診斷
1.1 MaterialDef TypeScript Interface¶
src/material-params/materials.ts 對應型別:
type MaterialId = string;
type PartType =
| "chassis"
| "body"
| "tire"
| "motor"
| "battery"
| "roller"
| "chip"
| "weapon";
interface MaterialDef {
id: MaterialId;
// === 物理欄位 ===
density: number; // g/cm³
yield_strength: number | null; // MPa
ultimate_strength: number | null; // MPa
friction: number; // 0-3
restitution: number; // 0-1
thermal_conductivity: number | null; // W/(m·K)
specific_heat: number | null; // J/(kg·K)
thermal_limit: number | null; // °C
rolling_resistance: number; // 基準 1.0,所有材質必填(fallback 防護)
// === 磁性身分(三選一,型別系統強制互斥;磁源強度由 Root Extras magnet_source_strength_n 決定,見 §8)===
magnetism_role: "passive" | "source" | "none";
magnetic_susceptibility: number | null; // 0-1,僅 role='passive' 有值;其他 role 為 null
// === Fluid 特性(runtime 行為標識,不參與檢核)===
is_fluid?: boolean;
deploy_behavior?: "grip_loss" | "sticky" | "freeze" | "burn" | "corrosive";
deploy_params?: Record<string, number>;
// === 硬規則(Stage 1 剃除違規指派 / Stage 3 拒收殘留,見 §4)===
forbidden_scopes?: ReadonlyArray<"vehicle" | "environment">;
allowed_part_types?: ReadonlyArray<PartType>;
// === UI 排序(軟提示,optional)===
display_order?: { vehicle?: number; environment?: number };
}
型別 & load-time 強制:
magnetism_role: 'passive'↔magnetic_susceptibility: number(必有值,0–1)magnetism_role: 'source' \| 'none'↔magnetic_susceptibility: null(必為 null)materials.ts載入時雙向 assert 上述不變式,違反即 throw(避免 malformed 資料靜默通過)- 公式端依
role === 'passive'narrow 後使用 susceptibility;其他 role 直接 force = 0,不觸碰 null 欄位
分類辨識:
forbidden_scopes為空 → vehicle-friendly(14 種,可用於零件與場地)forbidden_scopes = ['vehicle']且is_fluid = false→ environment-only(12 種,地表 + 場地特殊材質如magnet_floor)forbidden_scopes = ['vehicle']且is_fluid = true→ fluid(5 種,僅 weapon + 場地可用)
1.2 Gameplay capability 契約¶
材質欄位只有在正式 runtime 存在明確 consumer 時,才可宣稱具備對應 gameplay capability。資料列有值不等於該值在所有 scope、body 或接觸型態都會生效;文件、UI 與平衡討論不得把 fallback/分類資料描述成已接線玩法。
| 欄位/欄位族 | 已接線 capability 與適用邊界 |
|---|---|
density |
由實際水密 sub-mesh 體積合成質量/慣性;所有合法 vehicle region 都適用,fluid weapon payload 也按其實際幾何計入質量。這不代表存在浮力或 3D 流體密度模擬。 |
friction、restitution |
只供 solid collider 接觸;fluid sub-mesh 是 sensor,不建立實體碰撞回應,因此其數值僅是資料完整性的 fallback。 |
rolling_resistance |
tire/roller 與 solid surface 的實際接觸耗散;fluid sensor 不套用。 |
thermal_conductivity、specific_heat |
vehicle part 合成 heat capacity/ambient conductance;tire 與 solid surface 接觸時,以雙方 baked exchange factor 與實際 contact area 做熱交換。地表/entity 溫度是由天氣/場景決定的固定熱庫,不建立會被車輛加熱或冷卻的動態地面熱場。任一必要熱欄為 null 時該路徑不啟用。 |
thermal_limit |
只為可破壞 vehicle part 烘焙 thermalLimitC;null 表示無有意義閾值。Track Entity/地表是固定熱庫而非動態溫度實體,fluid sensor 也不執行過熱。 |
magnetism_role、magnetic_susceptibility |
passive 才會被磁源依 susceptibility 施力;source 只建立磁源身分,強度仍由 authored magnet_source_strength_n 提供;none 不參與。 |
is_fluid、deploy_behavior、deploy_params |
建立 sensor 與 grip-loss/sticky/freeze/burn/corrosive 觸發效果;不提供體積流場、浮力、黏度求解或一般流體阻力。sticky 的速度衰減是明示 gameplay effect,不等同 3D viscosity。 |
yield_strength、ultimate_strength |
只在現行 fatigue/衝擊/腐蝕/輪胎 wear capacity 公式明確取用時生效;數值本身不使物件可破壞,仍服從 §10。 |
若未來要讓目前無 consumer 的值產生新玩法,必須在同一變更中補 runtime 實作、決定性/有限值測試與本表契約,不能只改材質參數後宣稱生效。反之,只要 UGC 通過 schema、介面與資源規則,極端但合法的質量、尺寸與材質組合之數值穩定性屬 runtime 責任:以固定步長、有限值 guard、clamp/budget 與決定性退化處理,不另用公版外形比例限制封堵。
2. 31 種材質完整表¶
—= 無此欄位 / 不適用;null= 數學上不參與計算(不可破壞 / 不參與熱傳)。
| name | id | desc | forbidden | allowed_parts | density | yield_strength | ultimate_strength | friction | restitution | thermal_conductivity | specific_heat | thermal_limit | magnetism_role | magnetic_susceptibility | rolling_resistance | is_fluid | deploy_behavior | deploy_params |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| ABS 塑膠 | abs |
輕、便宜、易碎;熱絕緣;不耐熱 | — | — | 1.05 | 40 | 50 | 0.40 | 0.40 | 0.17 | 1300 | 80 | none | — | 0.95 | false | — | — |
| 聚碳酸酯 | pc |
韌性塑膠、平衡;中等耐熱 | — | — | 1.20 | 60 | 70 | 0.42 | 0.50 | 0.20 | 1170 | 130 | none | — | 0.95 | false | — | — |
| 聚乙烯 | pe |
滑、輕、低摩擦適合 roller | — | — | 0.95 | 25 | 30 | 0.05 | 0.45 | 0.42 | 2300 | 100 | none | — | 0.85 | false | — | — |
| 木材 | wood |
極輕、易破、復古主題;熱絕緣 | — | — | 0.70 | 30 | 50 | 0.55 | 0.30 | 0.15 | 1700 | 200 | none | — | 1.0 | false | — | — |
| 碳纖維複合 | carbon |
輕、強、對剪切力弱;高溫穩定 | — | — | 1.55 | 500 | 600 | 0.45 | 0.30 | 7 | 850 | 1000 | none | — | 0.9 | false | — | — |
| 玻璃纖維 | glass_fiber |
中等強度複合、便宜替代碳纖 | — | — | 2.00 | 200 | 400 | 0.50 | 0.25 | 0.40 | 800 | 800 | none | — | 0.9 | false | — | — |
| 矽膠 | silicone |
比 rubber 更軟、更耐熱 | — | — | 1.05 | 4 | 20 | 0.95 | 0.75 | 0.20 | 1300 | 200 | none | — | 1.1 | false | — | — |
| 橡膠 | rubber |
柔軟吸震、超彈跳、衝擊不破 | — | — | 1.10 | 5 | 25 | 1.20 | 0.85 | 0.16 | 1500 | 150 | none | — | 1.2 | false | — | — |
| 陶瓷 | ceramic |
硬但脆、易碎裂;頂級耐熱 | — | — | 3.50 | 100 | 200 | 0.65 | 0.10 | 30 | 900 | 1500 | none | — | 0.85 | false | — | — |
| 鎂合金 | magnesium |
超輕量金屬(比 aluminum 更輕且更強;易過熱) | — | — | 1.80 | 130 | 220 | 0.50 | 0.20 | 156 | 1023 | 350 | none | — | 0.9 | false | — | — |
| 鋁 | aluminum |
中重、易凹但難穿;散熱佳 | — | — | 2.70 | 90 | 120 | 0.50 | 0.20 | 237 | 900 | 400 | none | — | 0.9 | false | — | — |
| 鈦 | titanium |
最強、強度重量比最佳;散熱差(磁吸免疫=全非鋼材質預設,見 §8) | — | — | 4.50 | 750 | 880 | 0.55 | 0.18 | 22 | 522 | 1000 | none | — | 0.9 | false | — | — |
| 銅 | copper |
高密度、超佳散熱 | — | — | 8.00 | 70 | 220 | 0.45 | 0.10 | 401 | 385 | 500 | none | — | 0.85 | false | — | — |
| 鋼 | steel |
重、抗衝擊、可被磁吸 | — | — | 7.85 | 250 | 400 | 0.70 | 0.15 | 50 | 460 | 800 | passive | 1.0 | 0.95 | false | — | — |
| 柏油 | asphalt |
基準柏油路 | vehicle | — | 2.4 | 4 | 6 | 0.85 | 0.20 | 0.75 | 920 | null | none | — | 1.0 | false | — | — |
| 水泥 | concrete |
水泥地 | vehicle | — | 2.4 | 25 | 35 | 0.75 | 0.15 | 1.4 | 880 | null | none | — | 1.0 | false | — | — |
| 泥地 | dirt |
軟質土地(強度極低,數學上跳過 fatigue) | vehicle | — | 1.5 | null | null | 0.70 | 0.05 | 0.50 | 800 | null | none | — | 1.3 | false | — | — |
| 草地 | grass |
草地(強度極低,數學上跳過 fatigue) | vehicle | — | 0.4 | null | null | 0.65 | 0.10 | 0.10 | 1500 | null | none | — | 1.2 | false | — | — |
| 碎石 | gravel |
碎石地(強度極低,數學上跳過 fatigue) | vehicle | — | 1.8 | null | null | 0.70 | 0.10 | 0.30 | 800 | null | none | — | 1.4 | false | — | — |
| 沙地 | sand |
沙地(強度極低,數學上跳過 fatigue) | vehicle | — | 1.6 | null | null | 0.60 | 0.05 | 0.30 | 830 | null | none | — | 1.6 | false | — | — |
| 泥沼 | mud |
陷得深 | vehicle | — | 1.7 | null | null | 0.55 | 0.05 | 0.60 | 1500 | null | none | — | 1.6 | false | — | — |
| 積雪 | snow |
壓雪重 | vehicle | — | 0.3 | null | null | 0.30 | 0.10 | 0.10 | 2090 | null | none | — | 1.8 | false | — | — |
| 冰面 | ice_sheet |
光滑、低摩擦 | vehicle | — | 0.92 | null | null | 0.10 | 0.50 | 2.2 | 2100 | null | none | — | 0.8 | false | — | — |
| 青苔 | moss |
溼滑 | vehicle | — | 0.5 | null | null | 0.40 | 0.10 | 0.10 | 1500 | null | none | — | 1.3 | false | — | — |
| 水面 | water_surface |
hydroplaning | vehicle | — | 1.0 | null | null | 0.30 | 0.00 | 0.60 | 4180 | null | none | — | 1.5 | false | — | — |
| 磁鐵地板 | magnet_floor |
純主動磁源材質身分;強度由建模物件 Root Extras 宣告,未宣告 = 0(等於未磁化的鐵磁地板);N 極 = sub-mesh 面積加權平均法向(§8.3) | vehicle | — | 7.85 | 250 | 400 | 0.70 | 0.15 | 50 | 460 | null | source | — | 1.0 | false | — | — |
| 水 | water |
路面打滑 | vehicle | weapon | 1.0 | null | null | 0.10 | 0.10 | null | null | null | none | — | 1.0 | true | grip_loss |
{ grip_modifier: 0.5 } |
| 油 | oil |
打滑 + 拖慢 | vehicle | weapon | 0.9 | null | null | 0.05 | 0.05 | null | null | null | none | — | 1.0 | true | sticky |
{ grip_modifier: 0.3, velocity_decay_per_sec: 0.7 } |
| 結凍液 | freezing_fluid |
凍冷 | vehicle | weapon | 0.8 | null | null | 0.05 | 0.05 | null | null | null | none | — | 1.0 | true | freeze |
{ temperature_delta_per_sec: -20 } |
| 熔岩 | lava |
加熱 | vehicle | weapon | 2.5 | null | null | 0.20 | 0.10 | null | null | null | none | — | 1.0 | true | burn |
{ temperature_delta_per_sec: 30 } |
| 酸液 | acid |
腐蝕(走耐受度因子族) | vehicle | weapon | 1.2 | null | null | 0.05 | 0.05 | null | null | null | none | — | 1.0 | true | corrosive |
{}(fatigue 由耐受度公式決定) |
注 1:fluid sub-mesh 為 sensor(§6 規則 1)→ friction / restitution 不參與碰撞反應(僅作玩家硬塞非 weapon 部位的 fallback 防護);正常 deploy 行為由 deploy_behavior + deploy_params 驅動。唯 density 例外:仍計入 mass_g(§7 幾何質量恆對所有 sub-mesh 求和,含合法的 weapon fluid sub-mesh,如熔岩刃塗層)。
注 2:所有 31 種材質皆設 rolling_resistance。hinge tire/roller 與 solid surface 的實際
contact 以 tire × surface 成對套用;Vehicle 14 種與 fluid 5 種的值是該材質若合法成為 solid
接觸面的初估值,待 playtest 校準(基準 asphalt = 1.0)。fluid sensor 不套滾阻。
注 3:可破壞性由建模決定,不由材質的 yield/ultimate 決定(見 §10)。例如 asphalt yield=4 不代表 asphalt 地面可被擊破 — 它是 Fixed body 不標 destructible,仍不可破壞。
注 4:磁性身分由 magnetism_role enum 三選一強制互斥(見 §8)。magnet_floor 為純主動磁源身分(role: source),強度由建模物件 Root Extras magnet_source_strength_n 決定;steel 為純被動鐵磁(role: passive, magnetic_susceptibility: 1.0);其他材質皆 role: none。
注 5:magnet_floor 的物理欄位(density / yield / ultimate / friction / restitution / thermal_conductivity / specific_heat)目前鏡像 steel(= 磁化鋼地板);thermal_limit 不在鏡像之列——magnet_floor 屬環境材質、依環境慣例 thermal_limit = null(非鏡像 steel 的 800)。兩者為獨立材質:可保持一致、亦可各自調整;改 steel 物理時不會自動同步 magnet_floor,依需要決定是否一併調。
注 6:環境材質(12 種)的 thermal_conductivity / specific_heat 已接入 tire/roller 對 solid surface 的固定熱庫接觸:先烘焙量化 sqrt(k×density×specific_heat),再與輪組 factor、接觸面積及實際 normal impulse 合成熱導。entity 本身仍不模擬有限熱容量,地表熱庫溫度取 weather.temperature(算式表.md §6.5)。
3. Deploy Behavior 對接¶
| Behavior | 中文 | 機制 |
|---|---|---|
grip_loss |
打滑 | 經過時 grip × grip_modifier,由輪胎/roller 與地表的接觸牽引求解 |
sticky |
黏滯 | grip × grip_modifier(同上)+ 每幀 velocity ×= 1 − (1 − velocity_decay_per_sec) × dt(每秒保留率之線性化;decay^dt 的一階近似——runtime pow 屬超越函數、禁入共識路徑) |
freeze |
凍冷 | temperature_delta_per_sec × part.heatCapacityJPerC 轉為負 W 進單一熱 ledger;不受 passive thermal resist 折抵 |
burn |
灼熱 | temperature_delta_per_sec × part.heatCapacityJPerC 轉為正 W 進單一熱 ledger;受 passive thermal resist 折抵 |
corrosive |
腐蝕 | 接觸 sub-mesh 每秒 fatigue += K_ACID / sub_mat.ultimate × dt(耐受度因子族) |
4. 檢核邏輯¶
材質在 vehicle 場景使用(零件 GLB):
if 'vehicle' in material.forbidden_scopes:
if material.allowed_part_types contains 該零件類型:
✅ 通過(白名單例外)
else:
❌ 違規(處置見下)
材質在 environment 場景使用(場地 GLB):
if 'environment' in material.forbidden_scopes:
❌ 違規(處置見下)
else:
✅ 通過
違規處置(三階段分工):Stage 1 自動剃除違規材質指派(變未指派、不拒收上傳)→ Stage 2 編輯器過濾不可選 + 玩家重新指派 → Stage 3 嚴格拒收殘留違規(UGC機制.md §2.2 / §4.2、UGC上傳.md §3)。
is_fluid 不參與檢核,純為 runtime 行為標識。
5. UI 排序規則¶
各編輯器(vehicle / environment / 各零件類型)顯示材質清單:
- 過濾:根據檢核邏輯排除不允許的材質
- 排序(共識安全 + 可選覆蓋):
- 預設:用 §2 表格 array index(固定,跨 peer / 跨語系一致)
- 覆蓋:若材質設了
display_order.<scope>→ 用該值(小到大) - 不採用 locale-aware 排序:i18n 名稱排序會造成 peer 與語系間順序不一致,禁用
- 不提供「顯示全部」開關(避免誤用不適合的材質)
- UI 額外功能(不影響 spec canonical 順序):
- 編輯器可加「搜尋 / 過濾 / 依屬性排序」view 功能(如依 mass 排序)
- 這些是純客戶端 view,不影響任何 ledger / 共識邏輯
6. Runtime 規則¶
規則 1:fluid sub-mesh 為 sensor mode¶
- 視覺 mesh 保留(玩家自選 texture / shader)
- 不施力、不參與 rigid body 碰撞
- 接觸偵測仍存在(用於觸發 deploy_behavior)
規則 2:零件全 fluid fallback¶
若某顆零件 part 所有 sub-mesh 都 is_fluid: true:
- 該 part 從遊戲開始
broken = true - 立即套用部件破損規則(見 零件與場景.md)
- 散開的 fluid 落到地面成 deploy_zone
此規則為 runtime safety net。上傳檢核已擋下大部分情況;本規則處理 regulation 漏接或規則變更的 edge case。
規則 3:場地 fluid 永遠 active¶
場地 GLB 內 is_fluid: true sub-mesh:永遠 sensor mode + deploy_behavior active,不需 broken 條件。
規則 4:「水包塑膠」邊界 — 編輯器警告¶
Stage 2 對 part 的 6 個 cardinal 方向(±X / ±Y / ±Z)做投影檢查:若 ≥ 1 個方向上 fluid sub-mesh 是最外層(該方向上 sub-mesh 的最大座標等於 part AABB 對應面,誤差 < 0.5mm)→ 顯示警告:
「外層 fluid 包覆 rigid body collider — 其他玩家會穿透 fluid 層直接撞到內部 collider。視覺上像水但物理上不會擋人。確定要這樣設計嗎?」
玩家確認後上傳,後果自負(規則 1 + 規則 2 仍生效)。
7. 多材質零件的物理合成¶
| 物理量 | 合成方式 |
|---|---|
mass_g |
Σ(sub_volume × sub_material.density) |
stress / fatigue |
由碰撞 collider handle 取接觸 sub-mesh 的 yield / ultimate;車輛與 destructible Track Entity 均不得退回主材質 |
| 摩擦 / restitution | 接觸點所在 sub-mesh 對應值 |
| 鐵磁吸力 | 對每 canonical sub-mesh 施力 ∝ 磁源 strength_n × sub.magnetic_susceptibility(僅 role: passive 的 sub-mesh 受力;方向取實際 collider 世界中心,總 impulse 施於剛體 COM、不產生 torque;磁源不限武器,場地磁源同理) |
thermal_conductivity / specific_heat |
Pre-bake 直接算 heatCapacityJPerC=Σ(massKg×specific_heat)、依 exposed area 與 capped conductivity factor 算 ambientConductanceWPerC,並為每個 proxy 烘焙量化 thermal exchange factor,不合成平均值。Runtime 只用 current PhysicsManifest typed 值。 |
thermal_limit |
Pre-bake:取 weakest non-null sub-mesh(忽略 null;若全 null 則整體 null)→ Canonical PhysicsManifest.geometry.thermalLimitC。Runtime 只比較 hydrate 的 part.thermalLimitC 與 part.temperature,不讀 extras、不做 sub-mesh 級別重算。是否觸發 broken 由建模決定(見 §10) |
| watertight | 每 sub-mesh 各自水密;整顆體積 = Σ sub-mesh 水密體積 |
| 摩擦 / restitution(inter-body) | 上列係數屬實際接觸 collider 的材質。一般 collider 的 friction、restitution 由 Rapier CoefficientCombineRule::Average 合成;tire/roller friction 採 Average、restitution 固定採 Min。UGC 不得覆寫 combine rule,但逐 collider 材質係數必須保留。規則見 D-20260811-04。 |
8. 磁性系統 — 三選一身分¶
詳細公式見 算式表.md §5。本檔列出設計原則。
8.1 三種磁性身分(材質層 — enum 強制互斥)¶
magnetism_role 三選一(型別系統保證單一身分,無需額外 schema 檢核):
| 身分 | magnetism_role |
magnetic_susceptibility |
物理意義 | 範例 |
|---|---|---|---|---|
| 主動磁源 | source |
—(不適用) |
有 N/S 極身分;強度由建模物件決定 | magnet_floor |
| 被動鐵磁 | passive |
0–1(材料固有磁化率) |
無極性方向、會被磁源吸/斥;強度為材料固有屬性 | steel |
| 無磁性 | none |
—(不適用) |
不參與磁力 | 多數材質 |
8.2 磁源強度來源(強度層 — 分離設計)¶
材質型磁源(場地物件 / 部件)「成為磁鐵」的條件:sub-mesh 材質 magnetism_role: source 且 物件 Root Extras magnet_source_strength_n > 0,兩者缺一即無磁源效果。武器 magnet 為分支型例外(動態強度、不依賴材質 role,見下表第一列)。
| 磁源類型 | strength_n 來源 |
|---|---|
| 武器 magnet 分支 | 動態 = available_output_w × allocation_pct / 100 × K_MAGNET_FORCE(SOC 降額後的可供功率比例;持續場強、去 dt,算式表.md §5.1);不依賴材質 role |
| 場地物件磁源(任意 entity) | 靜態 = Root Extras magnet_source_strength_n(玩家建模時宣告,0–10 N,MAGNET_SOURCE_STRENGTH_N_MAX,protocol.md §3)+ sub-mesh 材質 magnetism_role: source |
| 車輛部件磁源(fallback 防護) | 正常情境不會發生 — magnet_floor 為 vehicle forbidden、目前無 vehicle-friendly source 材質,車輛部件無可用 source 材質。此 row 為防呆備援:若異常出現 source sub-mesh + Root Extras magnet_source_strength_n(如未來新增 vehicle-friendly source 材質、或 schema 漏網),runtime 仍照規則計算避免崩潰 |
設計理由:磁源強度依賴特定物件的磁化處理 / 線圈電流 / 永磁加工,不是材料本身屬性 → 移到建模層;被動鐵磁強度是材料固有屬性(磁化率)→ 留在材質層(
magnetic_susceptibility)。
8.3 N 極方向統一規則¶
依磁源類型自動推導(無獨立 n_pole_direction schema 欄位):
- 武器 magnet:
Axisempty +Z - 場地物件 / 部件磁源:sub-mesh 面積加權平均法向(pre-bake 寫入 extras;每 sub-mesh 各自一向量;退化〔近球對稱、平均趨零〕→ fallback node +Z)——磁源 ↔ 磁源內積需每源單一向量(算式表.md §5.3)
8.4 互動算式(算式表.md §5)¶
| 互動 | 用到的欄位 | 結果 |
|---|---|---|
| 磁源 → 鐵磁 | source.strength_n × target.magnetic_susceptibility × 1/r² |
純吸引 |
| 磁源 ↔ 磁源 | a.strength_n × b.strength_n × N 極夾角 × 1/r² |
同極斥、異極吸 |
| 鐵磁 ↔ 鐵磁 | (無互動) | 無力 |
算式不涉及 polarity 開關;吸/斥純由 N 極方向夾角決定。
9. 耐受度因子族(fatigue / acid / wear 統一公式)¶
所有持續性損耗共用接觸 sub-mesh 的 ultimate_strength 耐受度因子,不為每種來源另加
acid_resistance/wear_factor。衝撞、acid、輪胎 rolling/slip、熱加權、zone 去重與門檻公式只由
算式表.md §7–9 定義;產品層破壞語意見
遊戲機制.md §4。
10. 可破壞性 — 由建模決定,不由材質決定¶
⚠️ 核心原則:材質的
yield_strength/ultimate_strength/thermal_limit是材料強度與閾值數值,與「能否破壞 / 能否熱壞」無關。能否破壞由建模屬性決定。 即使 fluid 材質因疏忽被設定在不可破壞的建模上,仍維持不可破壞(建模優先於材質)。
10.1 可破壞性決策表(涵蓋衝撞 + 過熱兩條路徑)¶
| 建模條件 | 是否可破壞 | runtime 動作 |
|---|---|---|
| Dynamic body(vehicle parts) | ✅ 可破壞 | 用材質 ultimate_strength 算 fatigue;用 manifest geometry.thermalLimitC hydrate 的 part.thermalLimitC(§7)判過熱 |
Fixed/Kinematic body + destructible: true + physics: "default" |
✅ 可破壞 | 用材質 ultimate_strength 算 fatigue;達閾值時停用 intact body/colliders/完整 visual,依版本化 descriptor 重建純視覺碎片(entity 無溫度模擬、過熱路徑僅車輛部件,場地.md §9.3) |
| 場景 entity 未標 destructible(Fixed/Kinematic 皆同) | ❌ 不可破壞 | 跳過 fatigue(與材質 ultimate_strength / thermal_limit 值無關;entity 不執行溫度模擬,車輛部件恆可破壞、不適用此列) |
場景 entity + physics: "visual_only" |
❌ 不可破壞 | 無 collider,不參與物理(僅場景 entity 適用,車內部件不會出現此設定);即使誤標 destructible: true 仍不可破壞——visual_only 優先(無 collider 無從受力) |
sub-mesh is_fluid: true |
❌ 不可破壞 | sensor mode,不施力、不參與碰撞、不參與熱傳合成 |
10.2 Runtime 跳過條件(完整 skip 清單)¶
下列為 runtime 實際跳過計算的完整條件(前 2 列 = §10.1 決策派生、後 2 列 = 純數學 ÷0 / null 保護):
| 例外 | 判定 | 跳過項目 | 理由 |
|---|---|---|---|
| 場景 entity 未標 destructible(不論 body type) | destructible !== true(Fixed/Kinematic 皆同) |
fatigue | entity 需 destructible: true 才可破壞,未標即跳過(含會動的 kinematic 平台);entity 本來就不執行過熱檢查,車輛部件不適用(恆可破壞) |
| sub-mesh 是 fluid | is_fluid: true |
fatigue + 過熱合成 | sensor mode,不施力、不參與熱傳 |
sub-mesh ultimate_strength 為 null 或 0 |
數學退化保護 | fatigue | 避免 ÷0 |
part.thermalLimitC 為 null |
manifest pre-bake 結果(所有 sub-mesh thermal_limit 皆 null) |
過熱檢查 | 該 part 無有意義的熔點 |
10.3 三種破壞機制分工¶
| 場景 | 機制 | 觸發條件 |
|---|---|---|
| 車內部件破壞 | fatigue 累積式 + 一擊重傷 | Dynamic body parts;stress / ultimate 累積 |
| 場地物件破壞 | destructible entity + fatigue | destructible: true + physics: "default";fatigue 達 1.0 或一擊重傷時停用 intact 物理/visual,依 descriptor 顯示純視覺碎片,不建立 fragment body/collider |
| Fluid 部署效果 | deploy_behavior(非 fatigue) | sensor mode 觸發 zone;走 grip_loss / freeze / corrosive 等 |
10.4 規則 2 全 fluid part fallback(機制見 §6 規則 2)¶
全 fluid part(所有 sub-mesh is_fluid: true)→ broken = true + 部件破損規則,機制定義見 §6 規則 2、不在此重列。
置於本節(可破壞性)的意義:這是 runtime safety net、不是「fluid 材質可破壞」的證明 —— fluid 本身仍 sensor mode(不參與碰撞);fallback 只處理「玩家疏忽放錯位置」的 edge case。
11. 材質變更與廢止流程¶
11.1 變更場景與升版規則¶
詳細升版分類見 版本規範.md §3;本表為材質專屬流程。
| 場景 | 流程 | client_version | builtin_assets_version | derive_logic_version |
|---|---|---|---|---|
| 新增材質 | 1. spec §2 加 row(含 name + id + 物理欄位 + 可選 display_order)2. materials.ts 加 const3. PR review 確認 spec ↔ const 一致 |
major(觸 src/material-params/ path-based、版本規範.md §4;既有 GLB 不受影響,但 builtin/derive +1 擋配對 → 舊 client 須升) |
+1 | +1 |
改物理數值(如 yield_strength / thermal_limit) |
1. spec §2 改值 2. materials.ts 改 const3. PR review 比對 |
major(破壞 deterministic) | +1 | +1 |
改 desc / name |
spec §2 改文字(const 不動,i18n bundle 視需要更新) | patch(純文檔) | 不動 | 不動 |
改 id(rename) |
禁止直接 rename — 破壞已上鏈 GLB 引用;改走「新增新 id + 廢止舊 id」雙步(舊 id const 永久保留) | 新增 major + 廢止 minor | 新增 +1 / 廢止不動 | 新增 +1 / 廢止不動 |
| 廢止材質(永不物理刪除) | 1. 將 id 加入驗證層 DEPRECATED_MATERIAL_IDS 清單(client 隨附、登記於 protocol.md §3;非 protocol、刻意置於 src/material-params/ 等 path-based major 路徑之外〔版本規範.md §4〕、不觸發雙 bump;materials.ts const 一字不動)2. 效果:Stage 2 編輯器不可選、Stage 3 拒收新上鏈使用;已上鏈舊資產(UGC + 公版)照常載入與比賽 = 絕版品(§11.3) 3. 不走治理、不強制更新公版:公版若仍用該材質亦變絕版品、照常可玩;要清理公版另走一次獨立公版變更(非廢止前置) |
minor(const 值不動、determinism 不破、不擋配對;僅新上鏈驗證規則變更) | 不動 | 不動 |
鐵則:材質 id 一旦發布即 immutable,且材質清單 append-only——GLB 用 id 引用材質、引用內嵌於 CID 鎖死的內容,無從替既有資產「換材質」(B 軸資產遷移機制不適用於材質);「確認全網無已上鏈使用」於 permissionless P2P 亦不可驗證。新增便宜、廢止可行、物理刪除與 rename 不存在。
11.2 通用原則¶
- 不走治理層 ConfigUpdateEvent:物理性質是規則不是 config;治理只能改
economy_config_version(鑄幣 / 經濟參數),不能改物理常數。材質廢止亦不走治理——它是 client 發版的上傳驗證規則變更(操作流程見 流程/升版.md §8),非鏈上 config - 任何
materials.ts變動自動觸發 版本規範.md §13 CI 不變式:src/material-params/路徑變更 →builtin_assets_version+derive_logic_version雙 bump(版本規範.md §4 path-based);廢止標記不在此路徑(驗證層DEPRECATED_MATERIAL_IDS,見 §11.1)、path-based 規則零例外 - PR review 必須檢查 spec ↔ const 物理欄位一致(
name/desc為純文檔欄位不存於 const,i18n bundle 另行維護;CI 可加 schema 比對) - 任何已上鏈 GLB 的
materials[].id引用必須能在materials.ts找到對應 const(append-only 鐵則下恆成立);Stage 3 拒收引用不存在 id 的新上鏈;runtime 載入時缺 id = 資料異常 → 拒絕載入該資產(fail-fast 純防呆、不靜默 fallback,比照 零件與共用介面.md §2 loader 無 marker 拒載入慣例)
11.3 絕版品行為(廢止材質的舊資產)¶
廢止只擋新上鏈,不動已存在的資產。已上鏈、引用了廢止材質的 UGC 與公版資產一律 絕版品:
- 永久可玩:const append-only 保留 → 物理數值與廢止前完全相同;絕版品永不變 unusable(與 B 軸 schema 棄用 → unusable 生命週期不同,版本規範.md §17)。
- 決定性安全:廢止不碰物理 const,全場 8 人對同一顆 GLB 算出相同結果。
- 配對安全:廢止不 bump
builtin_assets_version(僅 client minor)→checkCompatibility六欄位仍相等 → 已更新與未更新的 client 仍可同房;兩邊共用同一份 const、物理一致,差別僅在下述提示(純 UI、各 client 用自有清單判斷、不需 pin 帳本檢查點)。
為何是 client minor 而非 protocol-major:DEPRECATED_MATERIAL_IDS 是僅作用於上傳時(Stage 2/3)的驗證清單、零賽中足跡。TEXT_BLACKLIST 的 DMCA pre-check 與可選聊天 starter list 也都是 minor 級本機清單資料,不進房間協商或賽中共識(protocol.md §4)。上傳時清單跨 peer 不一致無共識風險,故不擋配對。
房內提示(絕版材質揭露):開賽前若場內任一玩家零件或場地含廢止材質,房間等待頁顯示軟提示說明其存在(流程/配對.md §9);續留房 = 默認認同該場公平性(沿用「開賽前退出無懲罰」同意機制,版本規範.md §21)。提示不逐一點名材質 / 理由(避免 i18n 隨時間膨脹);廢止理由集中於 資產政策.md §2(隨廢止 PR 同步登記)。此提示性質是平衡揭露(材質物理沒變),與 §21 兩種「降版本 / schema 差異」提示正交。
fork 絕版品:fork = 新上鏈 → 撞 Stage 3「拒收廢止材質」→ 必須先在 Stage 2 換掉該材質才能上鏈(把生態推離問題材質)。
可逆(廢止 → 復用):社群若共識某廢止材質可回歸,從 DEPRECATED_MATERIAL_IDS 移除即復用(對稱 client minor)。因 const 從未刪除,復用零遷移、零風險。復用決策機制(如投票)不屬本專案範疇(可由外部平台舉辦);本檔僅定義「移出清單即復用」這個操作。
情境路由(材質出問題時走哪條):
| 情境 | 走法 | 結果 |
|---|---|---|
| 數值不合理 / 引擎變更需調參增減 | 改物理數值(§11.1)= major | const 原地改值,對全網所有用該材質資產追溯生效 |
| 不適合遊戲性 / 引擎變更使其不適 | 廢止(§11.1)= minor | 凍結既有為絕版品、只擋新建 |