5.4 方块模型与方块材质贴图实例化
在前几节的学习中,我们不难发现,光是有一般方块——即完整不透明方块,是解决不了我们的全部需求的。原版有大量不完整方块和不透明方块,比如台阶、楼梯就属于不完整方块,而玻璃、树叶等又属于不透明方块。
那么这一节,我们来介绍如何自定义方块模型和方块材质,也就是minecraft:geometry组件和minecraft:material_instances组件的应用。
方块模型
我们知道,台阶只占一半的方块体积,楼梯则占 3/4 的方块体积。除此之外,比如箱子、讲台、草、梯子等方块都属于不规则形状的方块。而它们的形状则由方块模型(Block Geometry) 决定。方块模型会定义方块以何种形状显示在世界中。
例如……如果我们现在想要制作一个泥土台阶,首先就要有一个台阶的模型。
基于 Blockbench 的数据驱动方块模型构建
方块模型的定义也是数据驱动的,只要我们给客户端一个方块模型,它就会自动解析这个数据驱动模型并渲染出来。然而,在不可视的曾经,想要手写代码绘制一个模型谈何容易?像是台阶、楼梯这种尚且简单的模型还能勉强应付,而像讲台、饰纹陶罐这种稍复杂一些的模型,手写代码就会变得十分艰难。这时候,我们就必须要介绍我们曾经介绍过的老朋友——Blockbench!
是的,bb 可以做到可视化模型的编写,这才是它的主业!我们现在赶紧来打开 bb,准备构造我们的第一个模型吧!
在新建一栏选择 Bedrock 版方块:

我们定义我们的模型 ID 为geometry.test_slab_bottom,代表下半砖模型,这样我们就给我们的模型标识符填写为test_slab_bottom。文件名习惯上也填写为同一个名字。

现在就正式进入到我们的模型构造环节了。有很多人看到这个界面不知该如何下手,那就先跟着我们的步骤走吧。首先第一步,我们先定义一个骨骼(Bone):

有必要解释一下,新增骨骼不是说我们搞了一根骨头或者头骨之类的东西,骨骼是一个抽象出来的概念,就好像动物的运动实际上可以只追踪骨骼一样,骨骼的运动会带动肌肉的运动,进而相当于动物体的运动,我们这里定义的骨骼也是类似的概念。一个方块模型可能由多个部件(Cube) 组成,为了使多个部件以同一种方式运动,我们就会把这些部件放到同一个骨骼里面去。到后面,有不少操作也是针对于特定骨骼进行操作的,比如部件的隐藏、方块面的剔除等。
我们可以右键刚创建的骨骼bone,将它重命名为block。然后,点一下“+”号,创建一个新的部件:

现在,你的界面上应该出现了一个新的块。我们可以按住鼠标中键来旋转界面,按住Shift + 鼠标中键来平移界面。上方和右侧都有可以控制这个部件大小的工具。

我们现在把它拉伸到半砖的大小(注意这里的 1 格代表的是方块的一个像素,也就是这里 16×16×16 的大小才对应原版一个完整方块的大小),读者可以自行尝试:

现在我们其实就可以保存这个模型了!在保存之前,先回到我们的资源包,在资源包下新建models,再在
models下新建
blocks:
RP_test:资源包
models:模型
blocks:方块模型
然后,我们把模型导出到刚刚新建的文件夹里:

现在如果一切正常,你的资源包应该长成这个样子:
RP_test:资源包
- ……
models:模型
blocks:方块模型
test_slab_bottom.geo.json:下半砖模型
如法炮制地,我们给出上半砖的模型,这里我们就不配图了,请读者自行尝试,起名叫test_slab_top。
RP_test:资源包
- ……
models:模型
blocks:方块模型
test_slab_bottom.geo.json:下半砖模型
test_slab_top.geo.json:上半砖模型
这样,我们就完成了模型的绘制。可以看到,利用 bb 可以让我们的模型绘制变得更加得心应手,只要你想,通过 bb 就都很容易做得出来。bb 还有很多其他的功能,比如对应的贴图绘制和显示调整功能,这些就留给读者自行探索了。
行为包定义调用模型与贴图
minecraft:geometry组件:调用自定义的方块模型
现在,我们要在我们的行为包里调用这个模型。对方块使用特殊模型需要用到minecraft:geometry组件。
我们首先先来定义泥土台阶,并且同时定义一个方块状态test:vertical_half和相关的方块置换:
{
"format_version": "1.21.90",
"minecraft:block": {
"description": {
"identifier": "test:dirt_slab",
"menu_category": { "category": "construction" },
"states": {
"test:vertical_half": [ "bottom", "top" ]
}
},
"components": {},
"permutations": [
{
"condition": "query.block_state('test:vertical_half') == 'bottom'",
"components": {}
},
{
"condition": "query.block_state('test:vertical_half') == 'top'",
"components": {}
}
]
}
}
同时定义方块的音效和翻译,但注意不需要提供贴图:
{
"format_version": "1.21.40",
...,
"test:dirt_slab": { "sound": "gravel" }
}
我们来根据 wiki 给出的泥土的相关数值,给出泥土半砖的基础组件:
"components": {
"minecraft:destructible_by_mining": { "seconds_to_destroy": 0.5 },
"minecraft:destructible_by_explosion": { "explosion_resistance": 0.5 },
"minecraft:map_color": "#976D4D",
"tag:dirt": {}
},
现在我们来关注不同方块状态的情况。对于不同的半砖,我们需要改变半砖的碰撞箱、选择箱和模型:
"permutations": [
{
"condition": "query.block_state('test:vertical_half') == 'bottom'",
"components": {
"minecraft:collision_box": { "origin": [ -8, 0, -8 ], "size": [ 16, 8, 16 ] },
"minecraft:selection_box": { "origin": [ -8, 0, -8 ], "size": [ 16, 8, 16 ] },
"minecraft:geometry": "geometry.test_slab_bottom"
}
},
{
"condition": "query.block_state('test:vertical_half') == 'top'",
"components": {
"minecraft:collision_box": { "origin": [ -8, 8, -8 ], "size": [ 16, 8, 16 ] },
"minecraft:selection_box": { "origin": [ -8, 8, -8 ], "size": [ 16, 8, 16 ] },
"minecraft:geometry": "geometry.test_slab_top"
}
}
]
这里,我们的模型直接选用了字符串类型,选择了特定的模型。当然,根据文档,也可以选择对象型的,但目前里面的功能我们暂时并不需要,所以就使用字符串型的写法即可。
minecraft:material_instances组件:定义自定义模型方块的贴图
但是,只有minecraft:geometry组件是不行的。根据该组件的要求,我们必须同时定义minecraft:material_instances组件。这个组件就是专门根据模型来应用贴图的,它的作用和blocks.json是一致的。我们在这里使用原版泥土的贴图:
"permutations": [
{
"condition": "query.block_state('test:vertical_half') == 'bottom'",
"components": {
"minecraft:collision_box": { "origin": [ -8, 0, -8 ], "size": [ 16, 8, 16 ] },
"minecraft:selection_box": { "origin": [ -8, 0, -8 ], "size": [ 16, 8, 16 ] },
"minecraft:geometry": "geometry.test_slab_bottom",
"minecraft:material_instances": {
"*": { "texture": "flattened_dirt" }
}
}
},
{
"condition": "query.block_state('test:vertical_half') == 'top'",
"components": {
"minecraft:collision_box": { "origin": [ -8, 8, -8 ], "size": [ 16, 8, 16 ] },
"minecraft:selection_box": { "origin": [ -8, 8, -8 ], "size": [ 16, 8, 16 ] },
"minecraft:geometry": "geometry.test_slab_top",
"minecraft:material_instances": {
"*": { "texture": "flattened_dirt" }
}
}
}
]
做一些解释:
这里,"*"代表应用到所有的面,也就是所有的面都引用相同的贴图 ID。如果要对特定面使用特定的贴图,就可以把"*"改为"east"、"west"等特定的面。
这里的贴图 ID 是直接从terrain_texture.json找的,就不再需要
blocks.json这个“中间商”定义了。在使用了
minecraft:material_instances组件定义了贴图的情况下,就没有必要再使用blocks.json定义贴图了,否则游戏会报错。
这里我们引用了在terrain_texture.json中定义的
flattened_dirt。如果读者有做过上一节的练习,应该清楚为什么我们不引用dirt贴图。
minecraft:material_instances组件的功能要比blocks.json来得更强,因为它除了定义贴图之外,还支持特定的面构成一组,使用特定的贴图。此外,它还可以用来控制光照渲染、面的材质等。在后面,我们定义方块的贴图和材质时应当优先考虑
minecraft:material_instances组件,而不再是blocks.json。但是,定义方块的音效还是要用
blocks.json的。
现在,我们来进入游戏实测一下效果吧!

当然,如果正常放置的话,只能放置下半砖,这时候我们就可以用/setblock命令放置上半砖。

或者,像半砖、旋转方块、可连接方块这些特殊方块,我们也可以用下一节会学到的方块特征来解决这种不便的问题!
方块材质
除了可以给方块贴图套用贴图之外,我们还可以规定方块面的材质(Material) 如何。所谓材质,指代的是使用何种性质的材料。例如,木桌使用木质材料制作,我们就说木桌的材质是木的。同理地,材质也可以说是铁的、金属的、透明的,这种描述材料本身性质的说法。
这里我们必须再次强调,读者必须注意:材质(Material)与贴图(Texture)不是一回事!社区总是喜欢叫 Texture Pack 为「材质包」,但这是错误的说法!Texture Pack 的官方译名为「纹理包」!
为什么会出现错误的说法?因为当初 Java 版也曾经历一段机翻的时光,在 Java 版 1.1 时期,Texture Pack 就曾被错译为「材质包」。
但现在我们看到,材质与贴图的概念是有本质区别的。如果说木桌的材质是木的,那么桌子上的桌布就可以认为是贴图——贴图(Texture)就只是将我们给定的图片贴到方块上而已。显然,Texture Pack 的工作是将贴图应用到方块上,而不是改变了方块的材质。因此,不应译为「材质包」,而应译为「纹理包」或「贴图包」。事实上,几乎只有 Minecraft 的社区会把 Texture Pack 常译为「材质包」。
由于错翻由来已久,拨乱反正的时间又特别的晚,因此社区形成了一股巨大的惯性,短时间内没有办法纠正。普通玩家在提起材质包这个名称时,我们只需要知道他们说的其实是贴图包即可。而对于我们这种专业的开发者来说,则必须要澄清、纠正这个概念。在后面,我们经常要同时提起贴图和材质的概念。
在方块部分,我们主要有这么几种材质(或者说渲染方法)可用:完全不透明、半透明和完全透明。此外,在 1.21.80 后,我们还有透明或半透明转不透明的材质,以实现远处的方块正常渲染。但总体上,无论特性或渲染方式如何变化,这些材质很大程度上都是围绕是否透明这个特性在展开的。
blend:半透明材质 背面剔除
现在我们可以把我们在练习 5.1 做的防爆玻璃拿出来,我们要把它改为透明材质,同时注意在blocks.json撤销对防爆玻璃的贴图的定义:
{
"format_version": "1.21.90",
"minecraft:block": {
"description": {
"identifier": "test:blast_proof_glass",
"menu_category": {
"category": "construction"
}
},
"components": {
"minecraft:destructible_by_explosion": false,
"minecraft:material_instances": { "*": { "texture": "glass", "render_method": "blend" } }
}
}
}
{
"format_version": "1.21.40",
...,
"test:blast_proof_glass": { "sound": "glass" },
...
}
我们这里使用的blend材质,是一种专门用于玻璃的半透明材质,它允许贴图中存在alpha通道(也就是不透明度通道)。我们曾在模块 1 学过,计算机领域常用RGB,也就是不同强度的红绿蓝三原色组合而成的值来代表一个颜色。而alpha通道也就是第 4 个通道(通常用A表示),代表颜色的不透明度。如果A为 0%,则代表这个颜色是完全透明的,也就是不可见的;而A为 100% 时,这个颜色就是完全不透明的。
读者在画贴图时也可以注意 bb 的这个不透明度设置,事实上这就是在指定A通道了。

当然,blend材质还有一个特别的点,就是存在背面剔除(Backface Culling)。我们都知道,对于一个立方体,以我们的视角只能看到它的 3 个面,而另外 3 个面则是不可见的。这样,我们就可以想方设法,不要让这些不可见的面渲染出来,毕竟渲染一个面是需要消耗性能的,更何况游戏内往往存在无穷无尽的方块,这就意味着无穷无尽的面要渲染,会大幅度提升渲染压力,降低客户端的性能。这种只渲染前面,而背面的方块面全部剔除掉,以提升性能的剔除方法,就叫做背面剔除。

面剔除示例
对于不透明的完整方块,这么做是不存在什么问题的,但对于透明方块来讲,情况就不是这样了。因为背面剔除是建立在玩家不可见背面的基础上的,但是透明方块却使得玩家可以看到背面!这样,是否存在背面剔除就会影响方块的渲染效果。有一个比较好的例子是玻璃和刷怪笼的渲染方法并不相同。读者可以看到:
- 对于玻璃来说,它使用的是
blend材质,存在背面剔除,故而我们看不到它的背面。 - 而刷怪笼使用的是
alpha_test材质(我们一会儿就会细说),而alpha_test材质是不会进行背面剔除的,所以刷怪笼的背面是清晰可见的。

背面剔除(左)与背面不剔除(右)的对比
现在我们定义了方块的材质和贴图,但不要忘记方块模型!不要忘记,minecraft:material_instances组件是必须配套minecraft:geometry组件的。但是我们这时候不希望引用特殊的方块模型该怎么办呢?这时候我们就可以使用官方为我们内置的模型了:
{
"format_version": "1.21.90",
"minecraft:block": {
"description": {
"identifier": "test:blast_proof_glass",
"menu_category": {
"category": "construction"
}
},
"components": {
"minecraft:destructible_by_explosion": false,
"minecraft:material_instances": { "*": { "texture": "glass", "render_method": "blend" } },
"minecraft:geometry": "minecraft:geometry.full_block"
}
}
}
minecraft:geometry.full_block是游戏内置的方块模型,代表一个完整方块。除了完整方块模型外,原版还支持一个minecraft:geometry.cross模型,类似于草、蒲公英等交叉贴图模型。关于原版的模型,读者可以查阅原版使用的方块模型。
然而,需要注意的是,原版模型并不是数据驱动模型,这意味着我们没有办法获取其模型的骨骼名,因此有很多操作(比如我们后面会讲到的面剔除等)都会失效。因此,事实上我们还是更推荐读者自创一个模型,难度不高,也更加可控:
RP_test:资源包
- ……
models:模型
blocks:方块模型
test_slab_bottom.geo.json:下半砖模型
test_slab_top.geo.json:上半砖模型
full_block.geo.json:完整方块模型
{
"format_version": "1.21.90",
"minecraft:block": {
"description": {
"identifier": "test:blast_proof_glass",
"menu_category": {
"category": "construction"
}
},
"components": {
"minecraft:destructible_by_explosion": false,
"minecraft:material_instances": { "*": { "texture": "glass", "render_method": "blend" } },
"minecraft:geometry": "geometry.full_block"
}
}
}
这样便大功告成了,我们来打开游戏实测一下效果!

嗯……看起来还是有所不同,显然相比于原版玻璃,内部的面全被渲染出来了!不是说有背面剔除吗,难道背面剔除失效了?事实上,如果我们只放一个玻璃的话,不难发现除了稍微暗点之外,背面剔除是在正常运行的:

也就是说,现在我们所见的所有的玻璃面都被认为是前面而不是背面。背面确实已经被剔除掉了,但我们期望的效果是内部的面也应该要剔除掉。这就涉及到我们之后要介绍的方块面剔除(Block Culling) 了。
alpha_test:透明材质 远距面剔除
现在让我们进一步深挖材质的奥秘。观察minecraft:material_instances组件的文档,我们发现alpha_test应该是一种和blend很像的材质。
为了分清这两种材质有何区别,我们把刚定义的玻璃分成两个方块状态,对test:render_method方块状态为alpha_test的方块使用alpha_test材质:
{
"format_version": "1.21.90",
"minecraft:block": {
"description": {
"identifier": "test:blast_proof_glass",
"menu_category": { "category": "construction" },
"states": {
"test:render_method": [ "blend", "alpha_test" ]
}
},
"components": {
"minecraft:destructible_by_explosion": false,
"minecraft:material_instances": { "*": { "texture": "glass", "render_method": "blend" } },
"minecraft:geometry": "geometry.full_block"
},
"permutations": [
{
"condition": "query.block_state('test:render_method') == 'alpha_test'",
"components": {
"minecraft:material_instances": { "*": { "texture": "glass", "render_method": "alpha_test" } }
}
}
]
}
}
可以看到,对于alpha_test材质而言,背面剔除便不再生效。

在查阅过文档后,我们还会发现alpha_test存在远距面剔除(Distant Culling)。所谓远距面剔除,其实就是指在距离过远时,是否还要渲染这个方块。对于alpha_test材质,在距离过远时就不再渲染这个方块了,这可以通过望远镜来观察:

因为全透明需要消耗的性能大,在距离过远时就停止渲染,这也是理所当然的,这可以提升客户端的性能。
以及,全透明和半透明的最大区别在于,全透明是不支持A通道的,我们只要把贴图换成白色染色玻璃就能立刻看到这一点:

可以看到,blend能够正确地渲染半透明的部分,而alpha_test就只能够将半透明的部分渲染为全透明。
在了解了透明度、背面剔除和远距面剔除这些概念后,相信读者应当就可以理解文档中剩下的那几种材质的含义了。
变换组件
对于特定的方块,例如半砖、可旋转方块来说,事实上对于不同方块状态的方块,使用的模型是基本一致的,无非是经过了旋转、偏移处理而已。对于这种情况,我们就可以使用minecraft:transformation了。
我们来观察原来的泥土台阶定义:
{
"format_version": "1.21.90",
"minecraft:block": {
"description": {
"identifier": "test:dirt_slab",
"menu_category": { "category": "construction" },
"states": {
"test:vertical_half": [ "bottom", "top" ]
}
},
"components": {
"minecraft:destructible_by_mining": { "seconds_to_destroy": 0.5 },
"minecraft:destructible_by_explosion": { "explosion_resistance": 0.5 },
"minecraft:map_color": "#976D4D",
"tag:dirt": {},
},
"permutations": [
{
"condition": "query.block_state('test:vertical_half') == 'bottom'",
"components": {
"minecraft:collision_box": { "origin": [ -8, 0, -8 ], "size": [ 16, 8, 16 ] },
"minecraft:selection_box": { "origin": [ -8, 0, -8 ], "size": [ 16, 8, 16 ] },
"minecraft:geometry": "geometry.test_slab_bottom",
"minecraft:material_instances": {
"*": { "texture": "flattened_dirt" }
}
}
},
{
"condition": "query.block_state('test:vertical_half') == 'top'",
"components": {
"minecraft:collision_box": { "origin": [ -8, 8, -8 ], "size": [ 16, 8, 16 ] },
"minecraft:selection_box": { "origin": [ -8, 8, -8 ], "size": [ 16, 8, 16 ] },
"minecraft:geometry": "geometry.test_slab_top",
"minecraft:material_instances": {
"*": { "texture": "flattened_dirt" }
}
}
}
]
}
}
我们注意到,这里面有大量的重复定义:都在定义选择箱碰撞箱为半砖大小,都在定义模型使用半砖模型,都使用泥土贴图。但是,两个方块置换的关系其实无非就是一上一下的关系。只要我们可以将下半砖向上平移半格,不就变成上半砖了么?所以我们其实可以大幅简化上面这段代码为:
{
"format_version": "1.21.90",
"minecraft:block": {
"description": {
"identifier": "test:dirt_slab",
"menu_category": { "category": "construction" },
"states": {
"test:vertical_half": [ "bottom", "top" ]
}
},
"components": {
"minecraft:destructible_by_mining": { "seconds_to_destroy": 0.5 },
"minecraft:destructible_by_explosion": { "explosion_resistance": 0.5 },
"minecraft:map_color": "#976D4D",
"tag:dirt": {},
"minecraft:collision_box": { "origin": [ -8, 0, -8 ], "size": [ 16, 8, 16 ] },
"minecraft:selection_box": { "origin": [ -8, 0, -8 ], "size": [ 16, 8, 16 ] },
"minecraft:geometry": "geometry.test_slab_bottom",
"minecraft:material_instances": {
"*": { "texture": "flattened_dirt" }
}
},
"permutations": [
{
"condition": "query.block_state('test:vertical_half') == 'top'",
"components": {
"minecraft:transformation": { "translation": [ 0, 0.5, 0 ] }
}
}
]
}
}
我们来对这段代码做一点解释:
- 首先,我们将选择箱、碰撞箱、模型和材质贴图实例化都移动到了根组件上,这意味着无论什么情况,都会应用其中的数据。
- 然后,我们将判定
test:vertical_half为bottom的方块置换直接删掉了——因为默认就是应用它的数据。 - 最后,我们检查到
test:vertical_half为top时,就尝试把方块向上移动 0.5 格。
相比于之前的写法,可以看到我们直接避免了大量的重复定义。甚至连模型我们都可以进一步简化,把模型geometry.test_slab_bottom和geometry.test_slab_top合并为一个geometry.slab作为半砖模型便已足够!合并的步骤就交给读者自行完成。
对于这种使用类似模型、选择箱碰撞箱等情况,我们就需要灵活使用minecraft:transformation组件,以避免重复定义。
总结
本节,我们介绍了如何自定义一个方块的模型、贴图和材质。
模型通常使用 Blockbench 制作。都 2026 年了,手写模型早已成为非主流中的非主流。写好的模型可以导出为xxx.geo.json的格式,放在资源包的models -
blocks文件夹中。通过
minecraft:geometry组件调用我们定义的模型,也可以用原版自带的模型,但通常来说我们还是更推荐读者自建模型。
使用minecraft:material_instances组件来把方块模型实例化,对方块使用特定的材质和贴图(最后再强调一次!材质和贴图不是一个概念!)。材质有透明(最常用的是blend和alpha_test)和不透明(opaque)之分。两种透明材质的表现有所不同,主要体现在全透明/半透明、背面剔除和远距面剔除几方面。
最后,我们还介绍了minecraft:transformation组件,可以对方块进行平移、旋转、缩放等操作,适合类似于台阶、楼梯的方块。
练习
从这一节开始,读者便应当能够开始编写不完整方块和透明方块了!这一节其实并没有讲很多新的内容,主要还是minecraft:geometry组件和minecraft:material_instances组件的应用。这两个组件往往需要混合使用。还是同样地,请读者积极完成本节的练习,我们后面的教程将会用得到它们!
- 我们在教程中实现了泥土台阶,请读者更进一步——实现玻璃台阶!并且注意使用玻璃的防爆和挖掘数据,详见玻璃 - 中文 Minecraft Wiki。
- 实现每个 MC 玩家都梦寐以求的——竖半砖(先做出木制的
test:oak_vertical_slab)!哇咔咔!定义test:cardinal_direction方块状态,可选值为north、south、west、east,分别对应玩家在面向北方、南方、西方、东方时放置的方块。注意灵活使用minecraft:transformation组件。我们在下一节就会介绍如何不依赖/setblock自动放置它们。 - 试阅读
minecraft:material_instances组件的文档,探究如何使得我们定义的防爆玻璃相比于原版玻璃不会偏暗。 - 之前我们定义的假石头,读者不难发现存在一个问题:在进入假石头后会将底部的方块面剔除,连带自己的方块面也被一并剔除。请使用合适的材质,使得这些面能够被渲染出来。

- 将我们之前定义的所有方块的贴图全部改用
minecraft:material_instances组件表达,而非blocks.json。对于完整方块而言,可以采用原版的完整方块模型
minecraft:geometry.full_block。 - 为我们在练习 5.1 定义的骰子添加一个方块状态
test:point,允许值为从1到6,分别代表骰子最上面的点数。 - 定义一种隐形基岩
test:invisible_bedrock,具有无法选中、耐爆炸、耐挖掘、贴图透明的性质,在物品栏中显示为屏障的贴图。贴图自备。提示:可定义一个同名的物品,并使用minecraft:block_placer组件中的replace_block_item解决。使用此思路也可以修改方块在物品栏中的性质。
练习题答案
-
BP_test/blocks/test/glass_slab.block.json 行为包定义
{
"format_version": "1.21.90",
"minecraft:block": {
"description": {
"identifier": "test:glass_slab",
"menu_category": { "category": "construction" },
"states": {
"test:vertical_half": [ "bottom", "top" ]
}
},
"components": {
"minecraft:destructible_by_mining": { "seconds_to_destroy": 0.3 },
"minecraft:destructible_by_explosion": { "explosion_resistance": 0.3 },
"minecraft:collision_box": { "origin": [ -8, 0, -8 ], "size": [ 16, 8, 16 ] },
"minecraft:selection_box": { "origin": [ -8, 0, -8 ], "size": [ 16, 8, 16 ] },
"minecraft:geometry": "geometry.slab",
"minecraft:material_instances": { "*": { "texture": "glass", "render_method": "blend", "face_dimming": false } }
},
"permutations": [
{
"condition": "query.block_state('test:vertical_half') == 'top'",
"components": {
"minecraft:transformation": { "translation": [ 0, 0.5, 0 ] }
}
}
]
}
}(这里我们禁用了方块面调暗的效果)

我们可以注意到侧面的方块面不太自然,在这里我们可以做进一步的处理。根据
minecraft:geometry组件的文档我们知道,我们可以定义模型时给特定的面分组。我们右键模型文件打开文件管理器,打开 bb,再将模型文件拖动到 bb 上即可打开模型:

因为我们要编辑的是侧面的贴图,我们对台阶做进一步的材质贴图实例编辑,将东西南北面均定义为
side,这样我们就可以在minecraft:geometry组件中直接定义为side面,确认后按下Ctrl + S保存模型:

我们来根据玻璃的贴图绘制一个新的贴图(参考贴图在这里
),在
terrain_texture.json定义为
glass_slab_side后,更改行为包定义如下,再大退重进即可:BP_test/blocks/test/glass_slab.block.json 行为包定义{
"format_version": "1.21.90",
"minecraft:block": {
"description": {
"identifier": "test:glass_slab",
"menu_category": { "category": "construction" },
"states": {
"test:vertical_half": [ "bottom", "top" ]
}
},
"components": {
"minecraft:destructible_by_mining": { "seconds_to_destroy": 0.3 },
"minecraft:destructible_by_explosion": { "explosion_resistance": 0.3 },
"minecraft:collision_box": { "origin": [ -8, 0, -8 ], "size": [ 16, 8, 16 ] },
"minecraft:selection_box": { "origin": [ -8, 0, -8 ], "size": [ 16, 8, 16 ] },
"minecraft:geometry": "geometry.slab",
"minecraft:material_instances": {
"*": { "texture": "glass", "render_method": "blend", "face_dimming": false },
"side": { "texture": "glass_slab_side", "render_method": "blend", "face_dimming": false }
}
},
"permutations": [
{
"condition": "query.block_state('test:vertical_half') == 'top'",
"components": {
"minecraft:transformation": { "translation": [ 0, 0.5, 0 ] }
}
}
]
}
}
这回,我们就有了一个比较满意的效果了。
-
这个问题难度稍微有点高,读者需要多加尝试。这里同时给出竖半砖的行为包定义和模型定义。
BP_test/blocks/test/oak_vertical_slab.block.json 行为包定义{
"format_version": "1.21.90",
"minecraft:block": {
"description": {
"identifier": "test:oak_vertical_slab",
"menu_category": { "category": "construction" },
"states": {
"test:cardinal_direction": [ "west", "south", "east", "north" ]
}
},
"components": {
"minecraft:collision_box": { "origin": [ -8, 0, -8 ], "size": [ 8, 16, 16 ] },
"minecraft:selection_box": { "origin": [ -8, 0, -8 ], "size": [ 8, 16, 16 ] },
"minecraft:geometry": "geometry.vertical_slab",
"minecraft:material_instances": { "*": { "texture": "oak_planks" } },
"minecraft:map_color": "#8F7748",
"minecraft:destructible_by_mining": { "seconds_to_destroy": 2 },
"minecraft:destructible_by_explosion": { "explosion_resistance": 3 },
"tag:minecraft:is_axe_item_destructible": {},
"tag:wood": {}
},
"permutations": [
{ "condition": "q.block_state('test:cardinal_direction') == 'north'", "components": { "minecraft:transformation": { "rotation": [ 0, 90, 0 ] } } },
{ "condition": "q.block_state('test:cardinal_direction') == 'west'", "components": { "minecraft:transformation": { "rotation": [ 0, 180, 0 ] } } },
{ "condition": "q.block_state('test:cardinal_direction') == 'south'", "components": { "minecraft:transformation": { "rotation": [ 0, 270, 0 ] } } }
]
}
}注意:
query.xxx的简写为q.xxx。RP_test/models/blocks/oak_vertical_slab.geo.json 模型文件{
"format_version": "1.12.0",
"minecraft:geometry": [
{
"description": {
"identifier": "geometry.vertical_slab",
"texture_width": 16,
"texture_height": 16,
"visible_bounds_width": 3,
"visible_bounds_height": 2.5,
"visible_bounds_offset": [0, 0.75, 0]
},
"bones": [
{
"name": "block",
"pivot": [0, 0, 0],
"cubes": [
{
"origin": [-8, 0, -8],
"size": [8, 16, 16],
"uv": {
"north": {"uv": [0, 0], "uv_size": [8, 16]},
"east": {"uv": [0, 0], "uv_size": [16, 16]},
"south": {"uv": [0, 0], "uv_size": [8, 16]},
"west": {"uv": [0, 0], "uv_size": [16, 16]},
"up": {"uv": [8, 16], "uv_size": [-8, -16]},
"down": {"uv": [8, 16], "uv_size": [-8, -16]}
}
}
]
}
]
}
]
}
-
实测关闭环境光遮蔽(
ambient_ocllusion为0.0)即可解决,使得防爆玻璃的渲染效果和原版玻璃效果相同。BP_test/blocks/test/blast_proof_glass.block.json 行为包定义{
"format_version": "1.21.90",
"minecraft:block": {
"description": {
"identifier": "test:blast_proof_glass",
"menu_category": { "category": "construction" }
},
"components": {
"minecraft:destructible_by_explosion": false,
"minecraft:material_instances": { "*": { "texture": "glass", "render_method": "blend", "ambient_occlusion": 0.0 } },
"minecraft:geometry": "geometry.full_block"
}
}
} -
这里移除掉假方块的方块置换,默认无碰撞箱。应用
double_sided材质以防止背面剔除。之后,我们还要学习方块面剔除,以剔除方块与方块之间的交界面。BP_test/blocks/test/blast_proof_glass.block.json 行为包定义{
"format_version": "1.21.90",
"minecraft:block": {
"description": {
"identifier": "test:fake_stone",
"menu_category": { "category": "construction" }
},
"components": {
"minecraft:collision_box": false,
"minecraft:geometry": "minecraft:geometry.full_block",
"minecraft:material_instances": { "*": { "texture": "stone", "render_method": "double_sided" } }
}
}
}
-
我们以曾经写过的黑色方块为例:
BP_test/blocks/test/black_block.block.json 行为包定义{
"format_version": "1.21.90",
"minecraft:block": {
"description": {
"identifier": "test:black_block",
"menu_category": { "category": "construction" },
"states": { "test:is_lit": [false, true] }
},
"components": {
"tag:test:colorful_block": {},
"minecraft:geometry": "minecraft:geometry.full_block",
"minecraft:material_instances": { "*": { "texture": "black_block" } }
},
"permutations": [
{ "condition": "q.block_state('test:is_lit')", "components": { "minecraft:light_emission": 15 } }
]
}
}相比于以前,我们还移除了一个
!q.block_state('test:is_lit')的判断,因为默认情况下方块就是不发光的。其他方块如法炮制,添加
minecraft:geometry组件和minecraft:material_instances组件,这里不再赘述。 -
BP_test/blocks/test/dice.block.json 行为包定义
{
"format_version": "1.21.90",
"minecraft:block": {
"description": {
"identifier": "test:dice",
"menu_category": { "category": "construction" },
"states": {
"test:point": [ 1, 2, 3, 4, 5, 6 ]
}
},
"components": {
"minecraft:geometry": "minecraft:geometry.full_block",
"minecraft:material_instances": {
"*": { "texture": "dice_1" },
"down": { "texture": "dice_2" },
"east": { "texture": "dice_3" },
"west": { "texture": "dice_4" },
"south": { "texture": "dice_5" },
"north": { "texture": "dice_6" }
}
},
"permutations": [
{
"condition": "q.block_state('test:point') == 2",
"components": { "minecraft:transformation": { "rotation": [180, 0, 0] } }
},
{
"condition": "q.block_state('test:point') == 3",
"components": { "minecraft:transformation": { "rotation": [0, 0, 90] } }
},
{
"condition": "q.block_state('test:point') == 4",
"components": { "minecraft:transformation": { "rotation": [0, 0, -90] } }
},
{
"condition": "q.block_state('test:point') == 5",
"components": { "minecraft:transformation": { "rotation": [-90, 0, 0] } }
},
{
"condition": "q.block_state('test:point') == 6",
"components": { "minecraft:transformation": { "rotation": [90, 0, 0] } }
}
]
}
}
-
这个方块需要同时定义方块和对应物品。注意物品中使用的
barrier贴图必须单独在item_texture.json定义。BP_test/blocks/test/invisible_bedrock.block.json 行为包定义{
"format_version": "1.21.90",
"minecraft:block": {
"description": {
"identifier": "test:invisible_bedrock",
"menu_category": {
"category": "construction"
}
},
"components": {
"minecraft:selection_box": false,
"minecraft:destructible_by_explosion": false,
"minecraft:destructible_by_mining": false,
"minecraft:geometry": "geometry.full_block",
"minecraft:material_instances": { "*": { "texture": "empty", "render_method": "alpha_test" } }
}
}
}BP_test/blocks/test/invisible_bedrock.item.json 行为包定义(物品){
"format_version": "1.21.90",
"minecraft:item": {
"description": {
"identifier": "test:invisible_bedrock",
"menu_category": {
"category": "construction"
}
},
"components": {
"minecraft:block_placer": { "block": "test:invisible_bedrock", "replace_block_item": true },
"minecraft:icon": "barrier",
"minecraft:display_name": { "value": "tile.test:invisible_bedrock.name" }
}
}
}