跳至主要內容

FreeMinecraftModels 模型製作注意事項

本頁記錄了 FreeMinecraftModels 程式碼庫中可見的當前製作細節。本頁刻意保守:專注於匯入/運行時契約,而非每個 Blockbench 工作流程偏好。

來源格式

FreeMinecraftModels 目前接受:

  • .bbmodel 檔案,用於可編輯的來源匯入
  • .fmmodel 檔案,用於精簡的運行時就緒模型資料

正常的匯入流程是:

  1. 將模型放入 plugins/FreeMinecraftModels/imports
  2. 執行 /fmm reload
  3. 讓 FreeMinecraftModels 將模型匯入活動模型集並重建生成的資源包

資料夾角色

plugins/FreeMinecraftModels/imports
plugins/FreeMinecraftModels/models
plugins/FreeMinecraftModels/models_disabled
  • imports 是手動模型匯入和官方包下載在處理前的接收資料夾
  • models 包含已安裝的活動模型內容
  • models_disabled 包含已下載或安裝但目前停用的包內容

較舊的安裝可能改為擁有一個大寫的 Models 資料夾。FreeMinecraftModels 的處理方式是:當標準的小寫 models 存在時優先採用它,只有在它不存在時才退回到舊有的 Models。在 Windows 與 macOS 上這兩個名稱本來就是同一個目錄;在區分大小寫的 Linux 檔案系統上,舊安裝仍可正常運作,但若兩個目錄同時存在,只有小寫的 models 會被讀取。如果你發現兩者都存在,請整併到 models 中。

模型 ID

  • 運行時模型 ID 來自檔案名稱,不含 .bbmodel.fmmodel 副檔名
  • 使用穩定、唯一的檔案名稱,因為 ID 是指令和 API 呼叫所解析的對象
  • Blockbench 動畫參考是基於名稱的,因此模型內部的重複或不明確命名比清晰、明確的命名方案更容易造成問題
  • 副檔名比對不區分大小寫,因此 .BBModel.FMModel 都會被接受

ID 正規化與衝突

檔案名稱在成為運行時模型 ID 與資源包檔名之前,會先被正規化

  1. 轉為小寫
  2. 所有不屬於 a-z0-9._- 的字元都會被替換成 _

因此 My Table.bbmodelmy table.bbmodelmy_table.bbmodel 全都會正規化成同一個 ID:my_table

在任何轉換開始之前,FreeMinecraftModels 會掃過整個 models 目錄樹,檢查是否有檔案會正規化成相同的 ID。當它發現衝突時:

  • 每一個發生衝突的檔案都會被拒絕 —— 它們全都不會被載入,因此不會出現「最後一個覆蓋前面」這種靜默行為
  • 該模型 ID 在本次載入流程的剩餘過程中都會被封鎖
  • 被拒絕的模型同樣會被排除在 Bedrock 自訂實體套件匯出之外
  • 主控台會出現:
[FMM Models] Rejected normalized model ID collision '<id>'. These files normalize to the same ID: <paths>. Rename the files so every normalized model ID is unique; no colliding model was loaded.

解決方法一律是重新命名檔案,讓正規化後的 ID 各不相同。最保險的習慣是從一開始就用小寫加底線來命名模型檔案(stone_table.bbmodel),這會讓檔案名稱與運行時 ID 完全一致,也徹底排除意外衝突的可能。

Blockbench 相容性

  • FreeMinecraftModels 會從 .bbmodel 讀取 meta.format_version,並依其主版本號分支
  • 缺少 meta 區塊、缺少 format_version,或數值無法解析,全都會退回到版本 4,並記錄一行指名該模型的資訊/警告訊息
  • 缺少 textures 陣列是可接受的,會被視為空的紋理清單而不會讓匯入器崩潰。之後 Bedrock 自訂實體匯出器會略過該模型,因為 Bedrock 匯出至少需要一張紋理
  • 提取出的紋理檔名會被正規化為單一個 .png 副檔名。像 body.jpgbody.PNGbody 這樣的來源名稱都會被寫成並參考為 body.png
  • format_version 4.x 及更早版本:骨骼直接從 outliner 樹讀取,該樹內嵌了骨骼名稱
  • format_version 5.x 及更新版本:outliner 結構改變了。outliner 現在是由裸 UUID 字串與 {uuid, isOpen, children} 字典組成的巢狀樹,沒有 name 鍵,而實際的骨骼資料(包含 name)則放在另一個扁平的 groups 陣列中。FMM 會以 UUID 把兩者接起來 —— 每個 outliner 節點都會被換成它在 groups 中對應的條目,然後遞迴合併子節點 —— 因此骨骼名稱、原點與旋轉都能正常解析
  • 手動編輯或以程式產生 .bbmodel 檔案時,值得知道的影響:
    • 缺少 groups 陣列的 v5 檔案會原封不動地被傳遞而未合併,因此其骨骼會失去名稱,保留前綴(tag_h_b_m_hitbox)也不再被辨識
    • outlinergroups 之間的 UUID 必須完全一致;找不到對應群組的 outliner 節點會被原樣保留,而不是被丟棄
    • 不要把 v5 的 format_version 與 v4 形式的 outliner 混用,反之亦然 —— 分支是依據宣告的版本選擇的,而非依據實際結構
  • 如果匯入日誌顯示模型格式與 FreeMinecraftModels 不相容,請先將其視為模型格式問題,而非 wiki 或指令問題

運行時相關的骨骼命名慣例

當前的轉換器和骨架管線會識別幾個命名慣例:

  • hitbox
    • 保留用於碰撞箱生成
    • 應該清晰地定義模型碰撞箱,而不是用作視覺骨骼
    • 必須是 outliner 中的頂層骨骼。匯入器只會在根層級尋找它;巢狀在其他骨骼內的 hitbox 群組會被當成一般骨骼
    • 必須恰好包含一個立方體,用來定義運行時的寬(x)、深(z)與高(y)。多餘的立方體會記錄 has more than one value defining a hitbox! Only the first cube will be used;空的 hitbox 骨骼會記錄 has a hitbox bone but no hitbox cube! 且不會生成碰撞箱
    • 永遠不會有動畫(指向 hitbox 的動畫軌道會被略過)、永遠不會被渲染,也會被排除在 Bedrock 幾何匯出之外。在 Bedrock 上,沒有 hitbox 骨骼的模型會退回為 1.0 x 2.0
  • tag_...
  • h_...
    • 被視為頭部骨骼
  • b_...
    • 非顯示骨骼(運行時隱藏)。用於不應在遊戲中渲染的結構性或組織性骨骼。
  • m_...
    • 騎乘點骨骼。帶有此前綴的每個骨骼會在模型上建立一個可騎乘的座位位置。玩家或實體可以在運行時被掛載到這些位置上。多個 m_ 骨骼會建立多個座位。由 MountPointManager 內部管理。

這些不僅僅是風格慣例;它們會影響轉換和運行時行為。

名稱標籤需要 tag_ 骨骼

這是已發佈內容出現無名怪物最常見的單一原因,因此值得直白地說清楚:

模型只有在含有名稱以 tag_ 開頭的骨骼時,才會取得名稱標籤。 沒有任何備援機制。

運作方式:

  • 匯入期間,任何名為 tag_... 的骨骼都會取得一個並行的自動生成「meta」骨骼(fmm_nametag_bone_<name>),並被標記為名稱標籤骨骼。管線中沒有其他任何環節會設定這個標記
  • 運行時,骨架會收集這些被標記的骨骼,並在該 tag_ 骨骼的原點生成一個文字顯示實體。它的位置與文字都會跟隨該骨骼
  • ModeledEntity.setDisplayName(...)setDisplayNameVisible(...) 會走訪這個集合。在沒有 tag_ 骨骼的情況下,該集合是空的,這兩個呼叫都會靜默地什麼都不做 —— 沒有錯誤、沒有警告、也沒有名稱

為什麼原版名稱標籤無法替你補上:

  • 動態模型會對客戶端隱藏其底層的生物實體(setVisibleByDefault(false),再加上隱形標記),所以原版怪物自己的名稱標籤也不會被渲染
  • 最終效果就是一個完全沒有名字的怪物,即使呼叫端外掛已經成功設定了顯示名稱

實用規則:

  • 如果模型代表一個具名實體(EliteMobs Boss、任務 NPC,或任何會被外掛呼叫 setDisplayName 的對象),請加上一個 tag_ 骨骼
  • 把它放在名稱標籤應該浮動的位置 —— 通常就在頭部上方
  • 該骨骼不需要有立方體;它只是一個位置錨點。特別是 tag_name 在生成物品模型定義時會被跳過,因此它永遠不會被渲染成幾何體
  • 允許有多個 tag_ 骨骼;它們每一個都會取得自己的文字顯示實體,並顯示相同的名稱
  • 如果你在主控台看到 nametag bone did not spawn name tag,代表該骨骼有被識別,但它的文字顯示實體生成失敗 —— 這與完全沒有 tag_ 骨骼是不同的問題

自由浮動立方體

宣告在 outliner 頂層、沒有所屬群組的立方體,會以裸 UUID 字串而非骨骼條目的形式進來。FreeMinecraftModels 會把它們附加到自動生成的根骨骼(freeminecraftmodels_autogenerated_root)上,讓它們仍然能被渲染。它們無法被動畫定址,因此請把任何你打算做動畫的東西放進真正的群組裡。

IK、空物件和定位器

當前程式碼確認支援:

  • Blockbench 空物件作為 IK 控制器
  • IK 鏈藍圖和運行時 IK 求解(FABRIK)
  • 定位器解析

只有當空物件在 .bbmodel 中的條目同時帶有 ik_source(鏈的起始骨骼)與 ik_target(鏈要伸向的骨骼或定位器)時,它才會成為 IK 控制器。lock_ik_target_rotation 也會一併被讀取。該鏈是從目標沿骨骼階層往上走訪到來源而被找出來的,因此兩者必須實際相連。

重要的實用限制:

  • 來源/目標的連結是以 UUID 建立的,因此改名也不會失效 —— 但若模型中缺少其中任一個 UUID,主控台會記錄 IK chain in model <model>: Could not find source bone with UUID ... / Could not find target with UUID ...,且該鏈會被略過
  • 如果走訪找不到從來源到目標的路徑,你會看到 Could not find path from source to target,該鏈也會被略過
  • 控制器的動畫查找是基於名稱的,因此控制器命名需要在模型結構和動畫資料之間保持穩定
  • 空物件上只有位置關鍵影格有意義 —— 它們會成為 IK 的目標偏移。空物件上的旋轉與縮放軌道會被忽略

關於 IK 每影格如何被驅動,請參閱動畫

1.21.4+ 輸出分割

FreeMinecraftModels 宣告 api-version: 1.21.4,因此 1.21.4 是最低伺服器版本,而你一定會取得的就是現代的物品模型定義配置:

plugins/FreeMinecraftModels/output/FreeMinecraftModels/assets/freeminecraftmodels/items

舊版(1.21.4 之前)的皮革馬鎧覆寫分支仍存在於程式碼中,但任何能載入當前外掛的伺服器都不會走到那裡。如果你正在閱讀舊筆記或查看舊的輸出資料夾,你看到的差異就來自於此。

展示模型 JSON(1.21.4+)

管理員可以在 .bbmodel.fmmodel 檔案旁邊放置一個同名的 .json 檔案(例如 table.bbmodel + table.json)。此 JSON 應從 Blockbench 匯出為「Java Block/Item」模型,定義物品在手持或物品欄中顯示時的外觀。

匯入時,FMM 會將此 JSON 複製到資源包輸出中,並自動將其中的裸紋理參考重寫為指向模型提取的紋理。如果不存在配套 JSON,該物品在遊戲中將顯示為普通紙張。

YML 中的自訂物品配置

配套的 .yml 設定檔(與模型同名)現在支援可選的物品欄位。如果設定了 material:,模型也可作為自訂可手持物品使用。完整的 YML 格式如下:

isEnabled: true
scripts:
- my_script.lua
material: DIAMOND_SWORD # optional — if set, model is also a custom item
name: '&b&lMy Custom Sword' # optional — display name
lore: # optional
- '&7A custom weapon'
enchantments: # optional — format: ENCHANTMENT_NAME,LEVEL
- SHARPNESS,5
- FIRE_ASPECT,2

material: 存在時,模型會與道具一起顯示在管理員內容瀏覽器中,並可作為功能性物品給予玩家。

Bedrock 和渲染路徑注意事項

  • Bedrock 支援取決於 sendCustomModelsToBedrockClientsV2(預設為 true;取代了較舊的 sendCustomModelsToBedrockClients 鍵)以及周圍的 Floodgate/Geyser/資源包路徑
  • 支援版本上的 Java 客戶端在啟用 useDisplayEntitiesWhenPossible 時可以使用展示實體渲染
  • 不要假設在 Java 客戶端上看起來正確的模型在你的 Bedrock 路徑上也會自動安全

實用製作建議

  • 保持檔案名稱穩定,因為它們會成為運行時 ID
  • 保持控制器和動畫命名明確,因為 Blockbench 動畫查找是基於名稱驅動的
  • 有意識地使用保留的虛擬骨骼名稱(hitboxtag_h_b_m_)—— 並記住任何要顯示名稱的模型都需要一個 tag_ 骨骼,否則它會靜默地沒有名字
  • 如果你希望狀態動畫自動觸發,請把它們命名為 spawnidlewalkattackdeath;其他一切都是需要你自己觸發的自訂動畫(請見動畫
  • 打算用於 /fmm disguise 的模型至少也應附帶 idle,並可加上 sneakjump,這兩者只有偽裝控制器會辨識(請見玩家偽裝
  • /fmm reload 之後驗證匯入的輸出,而不僅是在 Blockbench 內部
  • 驗證生成的資源包內容是否對應你的目標 Minecraft 版本線,特別是在 1.21.4+

弓和弩狀態模型

FMM 支援自訂弓和弩物品的自動拉弓動畫狀態。無需設定 -- 只需使用正確的後綴命名模型檔案,FMM 在資源包生成期間會自動偵測狀態集。

命名慣例

後綴用途
_idle手持物品,未拉弓或未裝填必需必需
_draw_start剛開始拉弓必需必需
_draw_half拉到一半必需必需
_draw_full完全拉滿必需必需
_charged已裝填的弩(箭或火箭)--必需

需要四個模型(除 _charged 外全部)。需要全部五個。

範例檔案配置

plugins/FreeMinecraftModels/imports/
cool_bow_idle.bbmodel
cool_bow_draw_start.bbmodel
cool_bow_draw_half.bbmodel
cool_bow_draw_full.bbmodel
cool_bow.yml <-- config uses the base name, not _idle

對於弩,你需要新增第五個檔案 cool_bow_charged.bbmodel

偵測機制

  • 偵測在資源包生成時(啟動時或 /fmm reload)自動進行。
  • 只有 _idle 模型在輸出包中獲得物品定義 JSON。拉弓和裝填狀態作為該定義中的條件條目參考。
  • 只有基礎名稱獲得 YML 設定檔。對於上述範例,設定是 cool_bow.yml,而不是 cool_bow_idle.yml

展示模型 JSON

每個狀態模型可以有自己的配套 .json 展示模型(例如 cool_bow_idle.jsoncool_bow_draw_full.json)。FMM 會自動將它們接入生成的物品定義中。有關生成的確切 JSON 結構,請參閱資源包輸出

超出範圍

本頁不嘗試保證:

  • 確切的 Blockbench UI 步驟
  • 藝術工作流程偏好
  • 較舊的本地 README 資料中描述的每個舊版 .bbmodel 怪癖

這些細節的變化速度比上述已驗證的運行時契約更快。