自定义模型
模型(Geometry)定义了实体、附着物(attachable)和方块的可视外形。基岩版使用自己独有的模型格式,与 Java 版完全不兼容。推荐使用 Blockbench 进行模型制作,它是目前社区最主流的基岩版模型编辑器。
前置条件
本页面主要讲解实体/附着物模型(minecraft:geometry 格式,format_version: "1.12.0")。方块模型使用中国版独有的 netease:block_geometry 格式,将在本文末尾简要介绍,详细内容请参考 自定义基础方块。在开始之前,建议先阅读 基础概念 和 自定义基础生物。
概述
在基岩版中,模型由一系列**骨骼(Bone)和方块体(Cube)**组成,用 JSON 文件描述。每个骨骼可以包含若干方块体,骨骼之间通过父子关系组成层级树。动画系统可以对骨骼进行旋转、平移、缩放,从而实现行走、攻击等效果。
模型文件放在资源包的 models/entity/ 目录下,扩展名为 .geo.json(也可以使用 .json,但 .geo.json 是推荐的命名约定)。
模型的使用场景:
| 使用者 | 引用方式 | 说明 |
|---|---|---|
| 实体(Entity) | 客户端实体定义 RP/entity/ 中的 geometry 字段 | 最常见的用法,为生物定义外形 |
| 附着物(Attachable) | RP/attachables/ 中的 geometry 字段 | 用于自定义 3D 物品,模型挂载在玩家手上 |
| 方块(Block) | blocks.json 中的 netease_model 或组件引用 | 使用中国版独有的 netease:block_geometry 格式 |
基岩版 vs Java 版
基岩版模型是纯 JSON 格式,不支持 Java 版的 .java 模型或 OBJ/FBX 等通用 3D 格式(方块模型也不支持)。如果你从 Java 版迁移,需要在 Blockbench 中重新制作或转换。
Blockbench 工作流
Blockbench 是一款免费、开源的体素模型编辑器,原生支持基岩版模型格式。以下是从零开始制作一个自定义生物模型的完整流程。
1. 创建项目
- 打开 Blockbench,点击 File > New > Bedrock Entity
- 填写项目设置:
- File Name:文件名,如
custom_mob - Model Identifier:模型标识符,如
geometry.mymod.custom_mob(必须以geometry.开头) - Texture Width / Height:贴图尺寸,如
64 x 32(必须是 2 的幂次或其整数倍) - 勾选 Box UV 可以使用盒式 UV 映射(适合简单模型),取消勾选则使用逐面 UV
- File Name:文件名,如
标识符命名规范
模型标识符必须以 geometry. 开头,推荐格式为 geometry.命名空间.模型名,例如 geometry.mymod.ghost。标识符中不能包含冒号(冒号在旧版格式中用于模型继承,现代格式已不支持)。只允许使用小写字母、数字、下划线和点号。
2. 搭建骨骼结构
- 在右侧 Outliner 面板中点击 Add Group 创建骨骼(Bone)
- 按
F2重命名骨骼,例如body、head、left_leg、right_leg - 通过拖拽调整骨骼的父子关系(将子骨骼拖到父骨骼上)
- 选中骨骼,在左下角设置 Pivot Point(旋转中心点)
骨骼是动画的基本单位。合理的骨骼层级对后续动画制作至关重要。
3. 添加方块体
- 选中目标骨骼,点击 Add Cube 添加方块体
- 使用顶部工具栏的移动、缩放、旋转工具调整方块体的位置和大小
- 方块体的尺寸以像素为单位,1 个单位 = 游戏中 1/16 格(即 1 像素大小)
4. 贴图与 UV 映射
- 在左侧面板中点击 Create Texture 创建空白贴图,或将 PNG 文件拖入 Blockbench
- 切换到 Paint 模式绘制贴图
- 如果使用逐面 UV(Per-face UV),可以在 UV 面板中单独调整每个面的映射区域
- 如果使用盒式 UV(Box UV),Blockbench 会自动展开贴图
5. 导出模型
- 点击 File > Export > Export Bedrock Geometry
- 保存到资源包的
RP/models/entity/目录 - 文件名建议为
模型名.geo.json,例如custom_mob.geo.json
导出后会生成一个标准的 format_version: "1.12.0" 格式的模型 JSON 文件。
模型文件格式
实体/附着物模型使用 format_version: "1.12.0" 格式。一个模型文件可以包含多个几何体定义。
顶层结构
{
"format_version": "1.12.0",
"minecraft:geometry": [
{
"description": { ... },
"bones": [ ... ]
}
]
}| 键 | 类型 | 说明 |
|---|---|---|
format_version | string | 固定为 "1.12.0" |
minecraft:geometry | array | 几何体数组,每个元素是一个完整的模型定义 |
description 字段
"description": {
"identifier": "geometry.mymod.custom_mob",
"texture_width": 64,
"texture_height": 32,
"visible_bounds_width": 2,
"visible_bounds_height": 2.5,
"visible_bounds_offset": [0, 1, 0]
}| 键 | 类型 | 说明 |
|---|---|---|
identifier | string | 模型的唯一标识符,必须以 geometry. 开头 |
texture_width | int | 贴图宽度(像素),用于计算 UV 坐标 |
texture_height | int | 贴图高度(像素),用于计算 UV 坐标 |
visible_bounds_width | float | 可选。可见范围宽度(格),用于视锥剔除。默认为 0 |
visible_bounds_height | float | 可选。可见范围高度(格),用于视锥剔除。默认为 0 |
visible_bounds_offset | array | 可选。可见范围偏移 [x, y, z],一般设为模型中心。默认为 [0, 0, 0] |
visible_bounds 的重要性
visible_bounds_width 和 visible_bounds_height 定义了模型的可见判定范围。如果设得太小,当实体在屏幕边缘时模型可能突然消失;如果设得太大,会增加不必要的渲染开销。对于标准体型的生物,width: 1 + height: 2 + offset: [0, 1, 0] 是合理的默认值。
完整示例:自定义生物模型
以下是一个包含 4 个骨骼(body、head、left_leg、right_leg)的完整自定义生物模型。该生物高约 1.5 格,身体为长方体,头部为正方体,两条腿在身体下方。
{
"format_version": "1.12.0",
"minecraft:geometry": [
{
"description": {
"identifier": "geometry.mymod.custom_mob",
"texture_width": 64,
"texture_height": 32,
"visible_bounds_width": 1,
"visible_bounds_height": 2,
"visible_bounds_offset": [0, 0.75, 0]
},
"bones": [
{
"name": "body",
"pivot": [0, 12, 0],
"cubes": [
{
"origin": [-4, 8, -3],
"size": [8, 8, 6],
"uv": [0, 0]
}
]
},
{
"name": "head",
"parent": "body",
"pivot": [0, 16, 0],
"cubes": [
{
"origin": [-3, 16, -3],
"size": [6, 6, 6],
"uv": [28, 0]
}
]
},
{
"name": "left_leg",
"parent": "body",
"pivot": [2, 8, 0],
"cubes": [
{
"origin": [0, 0, -1.5],
"size": [4, 8, 3],
"uv": [0, 14]
}
]
},
{
"name": "right_leg",
"parent": "body",
"pivot": [-2, 8, 0],
"cubes": [
{
"origin": [-4, 0, -1.5],
"size": [4, 8, 3],
"uv": [14, 14]
}
],
"mirror": true
}
]
}
]
}骨骼层级关系:
body (根骨骼)
├── head
├── left_leg
└── right_legUV 布局说明:
| 骨骼 | UV 起点 | 尺寸 (宽×高×深) | 占用贴图区域 |
|---|---|---|---|
| body | [0, 0] | 8×8×6 | 盒式 UV 展开 |
| head | [28, 0] | 6×6×6 | 盒式 UV 展开 |
| left_leg | [0, 14] | 4×8×3 | 盒式 UV 展开 |
| right_leg | [14, 14] | 4×8×3 | 镜像 left_leg |
在客户端实体中引用
将模型文件保存为 RP/models/entity/custom_mob.geo.json 后,在客户端实体定义中引用:
{
"format_version": "1.10.0",
"minecraft:client_entity": {
"description": {
"identifier": "mymod:custom_mob",
"materials": {
"default": "entity_alphatest"
},
"textures": {
"default": "textures/entity/custom_mob"
},
"geometry": {
"default": "geometry.mymod.custom_mob"
},
"render_controllers": [
"controller.render.default"
]
}
}
}骨骼 (Bones)
骨骼是模型的骨架结构单元。每个骨骼可以包含方块体、定位器,以及通过 parent 字段指定的父子关系。动画系统通过骨骼名称来对模型进行变换。
骨骼字段
| 键 | 类型 | 说明 |
|---|---|---|
name | string | 骨骼名称,在同一模型中必须唯一。动画通过此名称引用骨骼 |
parent | string | 可选。父骨骼的名称。省略时该骨骼为根骨骼 |
pivot | array(float) | 旋转中心点 [x, y, z],动画旋转时以此为轴心 |
rotation | array(float) | 可选。初始旋转角度 [rx, ry, rz](度),默认为 [0, 0, 0] |
cubes | array(object) | 可选。该骨骼包含的方块体列表 |
locators | object | 可选。定位器,用于粒子/拴绳等附着点 |
mirror | bool | 可选。是否镜像该骨骼下所有方块体的 UV。默认为 false |
骨骼层级
骨骼通过 parent 字段形成树状层级结构。当父骨骼旋转时,所有子骨骼会跟随旋转。这是实现关节动画的基础。
root ← 根骨骼,通常不可见,放在原点
├── body ← 身体
│ ├── head ← 头部,跟随身体移动
│ ├── leftArm ← 左臂
│ └── rightArm ← 右臂
├── leftLeg ← 左腿(挂在 root 下,不跟随身体旋转)
└── rightLeg ← 右腿Pivot(旋转中心)
pivot 是骨骼最重要的属性之一。它定义了骨骼旋转时的中心点。
- 手臂的 pivot 应设在肩膀位置,这样旋转时手臂会像真实关节一样摆动
- 头部的 pivot 应设在脖子底部,这样抬头/低头时看起来自然
- 腿的 pivot 应设在大腿根部(连接身体的位置)
{
"name": "head",
"parent": "body",
"pivot": [0, 24, 0],
"cubes": [
{
"origin": [-4, 24, -4],
"size": [8, 8, 8],
"uv": [0, 0]
}
]
}在上面的示例中,头部的 pivot 设在 [0, 24, 0](身体顶部),这样当动画旋转头部时,它会围绕脖子位置转动。
Pivot 与 Origin 的关系
pivot 定义旋转中心,origin 定义方块体的最小角位置。两者是独立的。通常将 pivot 设在骨骼与其父级的连接点(即关节位置),而 origin 是方块体的实际起始坐标。
方块体 (Cubes)
方块体是模型中的基本视觉元素。每个方块体是一个长方体(Box),可以有自己的位置、大小、旋转和 UV 映射。
方块体字段
| 键 | 类型 | 说明 |
|---|---|---|
origin | array(float) | 方块体最小角(左下后角)的坐标 [x, y, z] |
size | array(float) | 方块体的尺寸 [宽, 高, 深],单位为像素(1 像素 = 1/16 格) |
pivot | array(float) | 可选。方块体自身的旋转中心,仅当方块体有独立旋转时使用 |
rotation | array(float) | 可选。方块体的独立旋转 [rx, ry, rz](度) |
uv | array/object | UV 映射,见下方详细说明 |
inflate | float | 可选。膨胀值,正值让方块体在各方向上均匀扩大(不影响 UV),负值缩小。常用于制作外层覆盖(如盔甲层) |
mirror | bool | 可选。是否镜像该方块体的 UV。默认为 false |
UV 映射
基岩版支持两种 UV 映射方式:
盒式 UV(Box UV):
使用 [u, v] 数组指定 UV 起点,引擎自动按方块体尺寸展开六个面。这是最简单的方式,适合大多数方块体。
{
"origin": [-4, 12, -2],
"size": [8, 12, 4],
"uv": [16, 16]
}盒式 UV 的贴图展开规则(从左到右):
[上面]
[左面] [前面] [右面] [后面]
[下面]逐面 UV(Per-face UV):
使用对象格式,为每个面单独指定 UV 坐标和大小。可以精确控制每个面的贴图映射,也可以省略不需要渲染的面。
{
"origin": [-4, 0, -4],
"size": [8, 4, 8],
"uv": {
"north": { "uv": [0, 0], "uv_size": [8, 4] },
"south": { "uv": [0, 0], "uv_size": [8, 4] },
"east": { "uv": [8, 0], "uv_size": [8, 4] },
"west": { "uv": [8, 0], "uv_size": [8, 4] },
"up": { "uv": [16, 0], "uv_size": [8, 8] },
"down": { "uv": [16, 8], "uv_size": [8, 8] }
}
}每个面的字段:
| 键 | 类型 | 说明 |
|---|---|---|
uv | array(float) | 该面 UV 区域的左上角坐标 [u, v] |
uv_size | array(float) | 该面 UV 区域的宽高 [width, height] |
何时使用逐面 UV
当你需要以下功能时,使用逐面 UV:
- 移除某些不可见的面(减少面数,提升性能)
- 让不同面使用贴图上不同区域
- 精确控制 UV 坐标和大小
inflate 的用法
inflate 是一个非常实用的属性。正值会让方块体在所有方向上均匀膨胀,但 UV 映射保持不变。
常见用途:
- 盔甲/外层:在原始身体方块体外加一层
inflate: 0.25或inflate: 0.5的方块体,作为盔甲或衣服的外层 - 解决 Z-fighting:两个面重叠时用
inflate: 0.01微调来消除闪烁 - 缩小方块体:当方块体的某个维度小于 1 像素时 UV 会出问题,此时可以将尺寸设为 1 然后用负 inflate 缩小
{
"name": "hat",
"parent": "head",
"pivot": [0, 24, 0],
"cubes": [
{
"origin": [-4, 24, -4],
"size": [8, 8, 8],
"uv": [32, 0],
"inflate": 0.5
}
]
}上面的示例为头部添加了一个帽子层,比头部大 0.5 像素,常见于玩家模型的第二层。
定位器 (Locators)
定位器(Locator)是附着在骨骼上的命名点,用于在特定位置生成粒子、附着拴绳或放置其他效果。
格式
定位器定义在骨骼的 locators 字段中:
{
"name": "rightItem",
"pivot": [-6, 15, 1],
"parent": "rightArm",
"locators": {
"lead_hold": [-6, 15, 1]
}
}定位器的值是一个 [x, y, z] 坐标数组,表示定位器在模型空间中的位置。
常用定位器
| 定位器名称 | 用途 | 通常附着的骨骼 |
|---|---|---|
lead_hold | 拴绳的连接点 | rightItem 或 rightArm |
在粒子中使用
动画和粒子系统可以通过定位器名称找到对应的模型空间位置。例如,在动画中可以在定位器位置触发粒子效果:
{
"particle_effects": {
"effect_name": {
"effect": "mymod:flame_particle",
"locator": "lead_hold"
}
}
}玩家模型骨骼
了解玩家模型的骨骼结构对于制作附着物(Attachable)和自定义 3D 物品至关重要。附着物需要引用玩家模型的骨骼名称来确定挂载位置。
完整骨骼树(Steve 模型)
root
└── waist
└── body
├── head
│ └── hat
├── cape
├── jacket (body 外层)
├── leftArm
│ ├── leftSleeve (外层)
│ └── leftItem (持物骨骼)
└── rightArm
├── rightSleeve (外层)
└── rightItem (持物骨骼,含 lead_hold 定位器)
├── leftLeg (挂在 root 下)
│ └── leftPants (外层)
└── rightLeg (挂在 root 下)
└── rightPants (外层)关键骨骼说明
| 骨骼名称 | Pivot | 说明 |
|---|---|---|
root | [0, 0, 0] | 模型根节点,位于脚底 |
waist | [0, 12, 0] | 腰部,连接上下半身 |
body | [0, 24, 0] | 身体主体(8x12x4) |
head | [0, 24, 0] | 头部(8x8x8),Pivot 在脖子 |
hat | [0, 24, 0] | 头部外层,inflate: 0.5 |
rightArm | [-5, 22, 0] | 右臂(4x12x4) |
rightItem | [-6, 15, 1] | 右手持物点,3D 物品挂载在此 |
leftArm | [5, 22, 0] | 左臂(4x12x4) |
leftItem | [6, 15, 1] | 左手持物点 |
rightLeg | [-1.9, 12, 0] | 右腿(4x12x4) |
leftLeg | [1.9, 12, 0] | 左腿(4x12x4) |
附着物如何使用玩家骨骼
制作自定义 3D 物品时,附着物的模型需要与玩家的 rightItem 骨骼对齐。更多细节请参考 自定义3D物品。
{
"format_version": "1.10.0",
"minecraft:attachable": {
"description": {
"identifier": "mymod:custom_sword",
"materials": {
"default": "entity_alphatest"
},
"textures": {
"default": "textures/items/custom_sword"
},
"geometry": {
"default": "geometry.mymod.custom_sword"
},
"render_controllers": [
"controller.render.default"
]
}
}
}方块模型
中国版独有格式
方块模型使用 netease:block_geometry 格式,与实体的 minecraft:geometry 格式完全不同,不可混用。
中国版自定义方块支持使用 netease:block_geometry 格式的模型 JSON,让方块拥有非正方体的外观。方块模型文件位于资源包的 models/netease_block/ 目录下。
基本结构
{
"format_version": "1.13.0",
"netease:block_geometry": {
"description": {
"identifier": "mymod:custom_chair_model",
"textures": ["mymod:chair_texture"],
"item_texture": "mymod:chair_item",
"use_ao": false
},
"bones": [
{
"name": "root",
"pivot": [0, 0, 0],
"cubes": [
{
"origin": [2, 0, 2],
"size": [12, 6, 12],
"uv": {
"north": { "uv": [0, 0], "uv_size": [12, 6] },
"south": { "uv": [0, 0], "uv_size": [12, 6] },
"east": { "uv": [0, 6], "uv_size": [12, 6] },
"west": { "uv": [0, 6], "uv_size": [12, 6] },
"up": { "uv": [0, 12], "uv_size": [12, 12] },
"down": { "uv": [0, 12], "uv_size": [12, 12] }
}
}
]
},
{
"name": "back",
"parent": "root",
"pivot": [0, 0, 0],
"cubes": [
{
"origin": [2, 6, 12],
"size": [12, 10, 2],
"uv": {
"north": { "uv": [0, 0], "uv_size": [12, 10] },
"south": { "uv": [0, 0], "uv_size": [12, 10] }
}
}
]
}
]
}
}与实体模型的关键区别
| 特性 | 实体模型 (minecraft:geometry) | 方块模型 (netease:block_geometry) |
|---|---|---|
| format_version | 1.12.0 | 1.13.0 |
| 贴图引用 | 在客户端实体定义中引用 | 在 description.textures 数组中直接引用 terrain_texture 短名称 |
| 贴图尺寸限制 | 建议不超过 256x256 | 不能超过 64x64 |
| UV 模式 | 盒式 UV 和逐面 UV | 仅逐面 UV |
inflate | 支持 | 不支持 |
骨骼 enable 字段 | 不存在 | 支持 MoLang 条件显隐(配合 netease:connection) |
骨骼 texture 字段 | 不存在 | 支持为每个骨骼/方块体/面指定不同贴图索引 |
| 动画 | 支持骨骼动画 | 不支持 |
使用流程
- 使用 Blockbench 创建 自由模型 项目(不要勾选盒式 UV)
- 贴图尺寸最大 64x64
- 通过 MC Studio 导入模型,自动生成 JSON 到
models/netease_block/ - 在
blocks.json中用netease_model引用模型 identifier - 配合
minecraft:block_light_absorption(设为 0)避免方块变黑 - 如需透明效果,配合
netease:render_layer使用
更多方块模型细节请参考 自定义基础方块 - 方块模型。
模型优化建议
移动端性能有限,模型的复杂度直接影响帧率。以下是一些优化建议:
面数与方块体数量
| 指标 | 推荐值 | 上限 |
|---|---|---|
| 单个实体模型的方块体数量 | 50 以内 | 约 300(移动端建议不超过此值) |
| 单个骨骼内的方块体数量 | 20 以内 | 无硬性限制,但影响渲染性能 |
| 骨骼总数 | 30 以内 | 无硬性限制 |
| 同屏实体数量 | 控制在 20 以内 | 取决于模型复杂度 |
贴图优化
- 实体贴图推荐使用 64x64 或更小的分辨率,除非确实需要更多细节
- 多个简单实体可以共用同一张贴图以减少纹理切换
- 贴图尺寸应为 2 的幂次(16、32、64、128、256),否则可能导致渲染问题
- 避免使用超过 256x256 的贴图,移动端内存有限
减面技巧
- 使用逐面 UV 移除不可见的面(例如两个方块体紧贴的面)
- 对称模型使用
mirror: true共用 UV 空间 - 避免大量重叠的半透明方块体(会产生严重的过度绘制)
- 尽量减少骨骼层级深度(过深的层级在计算变换矩阵时开销更大)
方块体尺寸注意
方块体的每个维度至少应为 1 像素。当尺寸小于 1 时,UV 计算会将其向下取整为 0,导致该面的贴图出现拉伸或不可见。如果确实需要更薄的方块体,可以将尺寸设为 1 然后使用 inflate: -0.5 来缩小。
材质 (Materials)
模型的渲染效果取决于客户端实体定义中指定的材质。不同材质决定了透明度和发光等效果。
| 材质名称 | 说明 |
|---|---|
entity | 基础不透明材质 |
entity_alphatest | 支持透明像素(完全透明 or 完全不透明) |
entity_alphablend | 支持半透明像素 |
entity_emissive | 不透明,Alpha 通道用作自发光 |
entity_emissive_alpha | Alpha 通道用于自发光,纯黑+透明像素透明渲染 |
在客户端实体 JSON 中设置:
"materials": {
"default": "entity_alphatest"
}如果模型需要透明部分(如翅膀、玻璃效果),请使用 entity_alphatest 或 entity_alphablend。使用 entity_alphablend 时需要注意半透明排序问题。
常见问题
模型在游戏中不可见
可能原因:
- 模型文件路径错误 -- 确保文件在
RP/models/entity/目录下 - identifier 不匹配 -- 客户端实体中引用的
geometry标识符必须与模型文件中的description.identifier完全一致 - visible_bounds 太小 -- 如果模型较大但
visible_bounds设得很小,摄像机稍微移开模型就会被剔除。尝试增大visible_bounds_width和visible_bounds_height - format_version 错误 -- 实体模型应使用
"1.12.0",不要使用旧版格式 - 材质设置错误 -- 检查客户端实体定义中的
materials是否正确
贴图拉伸或错位
可能原因:
- texture_width/height 与实际贴图不一致 --
description中的texture_width和texture_height必须与 PNG 文件的实际像素尺寸一致 - 方块体尺寸小于 1 -- 盒式 UV 模式下,尺寸小于 1 的维度会导致 UV 计算错误。使用
inflate配合调整,或改用逐面 UV - UV 坐标超出贴图范围 -- 检查所有 UV 坐标是否在
[0, 0]到[texture_width, texture_height]范围内
骨骼旋转不正确
可能原因:
- Pivot 位置不对 -- 旋转中心应设在关节位置。如果手臂的 pivot 设在手臂中间而非肩膀,旋转效果会不自然
- 父子关系错误 -- 检查
parent字段。如果腿挂在 body 而不是 root 下,身体倾斜时腿也会跟着倾斜 - 动画引用的骨骼名不匹配 -- 动画文件中的骨骼名必须与模型中的
name完全一致(区分大小写)
方块模型变黑
在使用 netease:block_geometry 方块模型时,如果模型看起来是全黑的,需要在方块行为包 JSON 中添加:
"minecraft:block_light_absorption": {
"value": 0
}这是因为默认的光照吸收值为 15(完全不透光),导致方块内部没有光照。
半透明面闪烁(Z-fighting)
当两个面完全重叠时,渲染引擎无法决定哪个面在前,导致闪烁。解决方案:
- 给其中一个方块体添加
"inflate": 0.01或"inflate": -0.01,让两个面微微错开 - 重新调整方块体位置,避免完全重叠
