FreeMinecraftModels 模型製作注意事項
本頁記錄了 FreeMinecraftModels 程式碼庫中可見的當前製作細節。本頁刻意保守:專注於匯入/運行時契約,而非每個 Blockbench 工作流程偏好。
來源格式
FreeMinecraftModels 目前接受:
.bbmodel檔案,用於可編輯的來源匯入.fmmodel檔案,用於精簡的運行時就緒模型資料
正常的匯入流程是:
- 將模型放入
plugins/FreeMinecraftModels/imports - 執行
/fmm reload - 讓 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 與資源包檔名之前,會先被正規化:
- 轉為小寫
- 所有不屬於
a-z、0-9、.、_與-的字元都會被替換成_
因此 My Table.bbmodel、my table.bbmodel 與 my_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.jpg、body.PNG或body這樣的來源名稱都會被寫成並參考為body.png format_version4.x及更早版本:骨骼直接從outliner樹讀取,該樹內嵌了骨骼名稱format_version5.x及更新版本:outliner 結構改變了。outliner現在是由裸 UUID 字串與{uuid, isOpen, children}字典組成的巢狀樹,沒有 name 鍵,而實際的骨骼資料(包含name)則放在另一個扁平的groups陣列中。FMM 會以 UUID 把兩者接起來 —— 每個 outliner 節點都會被換成它在groups中對應的條目,然後遞迴合併子節點 —— 因此骨骼名稱、原點與旋轉都能正常解析- 手動編輯或以程式產生
.bbmodel檔案時,值得知道的影響:- 缺少
groups陣列的 v5 檔案會原封不動地被傳遞而未合併,因此其骨骼會失去名稱,保留前綴(tag_、h_、b_、m_、hitbox)也不再被辨識 outliner與groups之間的 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.0x2.0
tag_...- 模型取得名稱標籤的唯一方式。請見下方的名稱標籤需要
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 動畫查找是基於名稱驅動的
- 有意識地使用保留的虛擬骨骼名稱(
hitbox、tag_、h_、b_、m_)—— 並記住任何要顯示名稱的模型都需要一個tag_骨骼,否則它會靜默地沒有名字 - 如果你希望狀態動畫自動觸發,請把它們命名為
spawn、idle、walk、attack與death;其他一切都是需要你自己觸發的自訂動畫(請見動畫) - 打算用於
/fmm disguise的模型至少也應附帶idle,並可加上sneak與jump,這兩者只有偽裝控制器會辨識(請見玩家偽裝) - 在
/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.json、cool_bow_draw_full.json)。FMM 會自動將它們接入生成的物品定義中。有關生成的確切 JSON 結構,請參閱資源包輸出。
超出範圍
本頁不嘗試保證:
- 確切的 Blockbench UI 步驟
- 藝術工作流程偏好
- 較舊的本地 README 資料中描述的每個舊版
.bbmodel怪癖
這些細節的變化速度比上述已驗證的運行時契約更快。