本篇教程的视频

本篇教程的源代码

Github地址:TutorialMod-Custom Item & Block-1.21

介绍

在本期教程中,我们将使用BlockBench来制作自定义的方块和物品模型

因为在实际开发过程中,我们可能会需要一些特殊的模型,比如各种工业设备、家具、装饰物品等等,而原版的模型并不能满足我们的需求,这个时候我们就需要自己制作模型了

这期教程其实非常简单,前面我们已经写过了物品方块的注册,无非在于本期教程使用的模型BlockBench制作的,而不是原版的模型

不过,前面我们制作方块实体的时候,也用到了BlockBench制作的那些模型,而这一期我们来详细讲讲如何使用这些自定义的模型

后面两期教程是这篇教程的衍生,讲讲自定义的方块状态BlockState),包括方块朝向和可连接方块的方块状态

当然,BlockBench的使用教程我这里就不讲了,哔哩哔哩上也有很多教程,大家可以去看看,后面我们也将使用它来制作我们的生物实体模型

另外,在建模前,我们要选择Java版模型这个模块!!!不要选择其他的!!!

Java版支持的模型文件是json格式的,其他模块无法导出json格式的模型文件,同样的,Java版模型的限制也在这个模块的介绍中有

至于obj格式的模型,游戏原生的渲染器是不支持的,而且Fabric也没有obj模型的加载器,但有从Forge搬过来的第三方库,我们后面可以讲讲

自定义物品

注册物品

1
public static final Item SIMPLE_ITEM = registerItems("simple_item", new Item(new Item.Settings()));

首先我们注册一下我们的物品,这里就注册一个最简单的物品,如果你还想和我们前面写的探矿器一样,那就自定义一个物品类,然后实例化它

加入物品栏

1
entries.add(ModItems.SIMPLE_ITEM);

数据文件

语言文件

1
translationBuilder.add(ModItems.SIMPLE_ITEM, "Simple Item");

模型文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
{
"credit": "Made with Blockbench",
"textures": {
"0": "tutorialmod:item/simple_item",
"particle": "tutorialmod:item/simple_item"
},
"elements": [
{
"from": [7, 0, 7],
"to": [9, 2, 9],
"rotation": {"angle": 0, "axis": "y", "origin": [7, 0, 7]},
"faces": {
"north": {"uv": [3, 12, 5, 14], "texture": "#0"},
"east": {"uv": [12, 3, 14, 5], "texture": "#0"},
"south": {"uv": [5, 12, 7, 14], "texture": "#0"},
"west": {"uv": [12, 5, 14, 7], "texture": "#0"},
"up": {"uv": [9, 14, 7, 12], "texture": "#0"},
"down": {"uv": [14, 7, 12, 9], "texture": "#0"}
}
},
{
"from": [7, 14, 7],
"to": [9, 16, 9],
"rotation": {"angle": 0, "axis": "y", "origin": [7, 14, 7]},
"faces": {
"north": {"uv": [9, 12, 11, 14], "texture": "#0"},
"east": {"uv": [12, 9, 14, 11], "texture": "#0"},
"south": {"uv": [11, 12, 13, 14], "texture": "#0"},
"west": {"uv": [13, 11, 15, 13], "texture": "#0"},
"up": {"uv": [15, 15, 13, 13], "texture": "#0"},
"down": {"uv": [5, 14, 3, 16], "texture": "#0"}
}
},
{
"from": [6.5, 2, 6.5],
"to": [9.5, 14, 9.5],
"rotation": {"angle": 0, "axis": "y", "origin": [7.5, 2, 7.5]},
"faces": {
"north": {"uv": [0, 0, 3, 12], "texture": "#0"},
"east": {"uv": [3, 0, 6, 12], "texture": "#0"},
"south": {"uv": [6, 0, 9, 12], "texture": "#0"},
"west": {"uv": [9, 0, 12, 12], "texture": "#0"},
"up": {"uv": [3, 15, 0, 12], "texture": "#0"},
"down": {"uv": [15, 0, 12, 3], "texture": "#0"}
}
}
],
"display": {
"thirdperson_righthand": {
"translation": [0, 3, 1],
"scale": [0.55, 0.55, 0.55]
},
"thirdperson_lefthand": {
"translation": [0, 3, 1],
"scale": [0.55, 0.55, 0.55]
},
"firstperson_righthand": {
"rotation": [0, -90, 25],
"translation": [1.13, 3.2, 1.13],
"scale": [0.68, 0.68, 0.68]
},
"firstperson_lefthand": {
"rotation": [0, -90, 25],
"translation": [1.13, 3.2, 1.13],
"scale": [0.68, 0.68, 0.68]
},
"ground": {
"translation": [0, 2, 0],
"scale": [0.5, 0.5, 0.5]
},
"gui": {
"rotation": [30, 225, 0],
"scale": [0.625, 0.625, 0.625]
},
"head": {
"rotation": [0, 180, 0],
"translation": [0, 13, 7]
},
"fixed": {
"rotation": [0, 180, 0]
}
}
}

简单的一个物品模型,贴图也是自动生成的,不想自己做就复制这里的好了

然后你记得在显示模式里面调节一下物品的显示位置,不然显示得会很奇怪

然后也不要忘了贴图文件

自定义方块

方块类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class SimpleBlock extends Block {
public static final VoxelShape SHAPE = Stream.of(
Block.createCuboidShape(0, 0, 0, 16, 2, 16),
Block.createCuboidShape(0, 14, 0, 16, 16, 16),
Block.createCuboidShape(0, 2, 2, 16, 14, 16)
).reduce((v1, v2) -> VoxelShapes.combineAndSimplify(v1, v2, BooleanBiFunction.OR)).get();
public SimpleBlock(Settings settings) {
super(settings);
}

@Override
protected VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
return SHAPE;
}
}

我们这里先写一个自定义的方块类,继承Block,然后我们写一个VoxelShape,这个是方块的碰撞箱

方块的碰撞箱可以用BlockBench生成,不过需要一个插件Mod Utils,这个插件可以在BlockBench的插件界面里面下载

安装好这个插件之后,在导出这个菜单中,就会有一个Export Voxelshape的选项,然后就可以导出碰撞箱了

但是这个还不完全智能,你得将所有的体块放在一个叫"VoxelShapes"的组下才能导出,名字不能错,大小写也是

然后在后面的教程中,我们还将根据我们的方块朝向来设置碰撞箱

注册方块

1
public static final Block SIMPLE_BLOCK = register("simple_block", new SimpleBlock(AbstractBlock.Settings.copy(Blocks.STONE)));

然后我们注册这个方块,这里我们注册的是一个最简单的方块,实例化我们写的SimpleBlock

加入物品栏

1
entries.add(ModBlocks.SIMPLE_BLOCK);

数据文件

语言文件

1
translationBuilder.add(ModBlocks.SIMPLE_BLOCK, "Simple Block");

模型文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
{
"credit": "Made with Blockbench",
"texture_size": [64, 64],
"textures": {
"0": "tutorialmod:block/simple_block",
"particle": "tutorialmod:block/simple_block"
},
"elements": [
{
"from": [0, 0, 0],
"to": [16, 2, 16],
"faces": {
"north": {"uv": [4, 11, 8, 11.5], "texture": "#0"},
"east": {"uv": [0, 11.5, 4, 12], "texture": "#0"},
"south": {"uv": [4, 11.5, 8, 12], "texture": "#0"},
"west": {"uv": [11.5, 6.5, 15.5, 7], "texture": "#0"},
"up": {"uv": [4, 4, 0, 0], "texture": "#0"},
"down": {"uv": [4, 4, 0, 8], "texture": "#0"}
}
},
{
"from": [0, 14, 0],
"to": [16, 16, 16],
"rotation": {"angle": 0, "axis": "y", "origin": [0, 14, 0]},
"faces": {
"north": {"uv": [11.5, 7, 15.5, 7.5], "texture": "#0"},
"east": {"uv": [11.5, 7.5, 15.5, 8], "texture": "#0"},
"south": {"uv": [11.5, 8, 15.5, 8.5], "texture": "#0"},
"west": {"uv": [11.5, 8.5, 15.5, 9], "texture": "#0"},
"up": {"uv": [8, 4, 4, 0], "texture": "#0"},
"down": {"uv": [8, 4, 4, 8], "texture": "#0"}
}
},
{
"from": [0, 2, 2],
"to": [16, 14, 16],
"rotation": {"angle": 0, "axis": "y", "origin": [0, 12, 0]},
"faces": {
"north": {"uv": [8, 3.5, 12, 6.5], "texture": "#0"},
"east": {"uv": [8, 6.5, 11.5, 9.5], "texture": "#0"},
"south": {"uv": [4, 8, 8, 11], "texture": "#0"},
"west": {"uv": [8, 9.5, 11.5, 12.5], "texture": "#0"},
"up": {"uv": [4, 11.5, 0, 8], "texture": "#0"},
"down": {"uv": [12, 0, 8, 3.5], "texture": "#0"}
}
}
],
"display": {
"thirdperson_righthand": {
"rotation": [75, 45, 0],
"translation": [0, 2.5, 0],
"scale": [0.375, 0.375, 0.375]
},
"thirdperson_lefthand": {
"rotation": [75, 45, 0],
"translation": [0, 2.5, 0],
"scale": [0.375, 0.375, 0.375]
},
"firstperson_righthand": {
"rotation": [0, 45, 0],
"scale": [0.4, 0.4, 0.4]
},
"firstperson_lefthand": {
"rotation": [0, 225, 0],
"scale": [0.4, 0.4, 0.4]
},
"ground": {
"translation": [0, 3, 0],
"scale": [0.25, 0.25, 0.25]
},
"gui": {
"rotation": [30, 225, 0],
"scale": [0.625, 0.625, 0.625]
},
"fixed": {
"scale": [0.5, 0.5, 0.5]
}
}
}

这个是方块的模型文件,同样的,贴图也是自动生成的,不想自己做就复制这里的好了

当然,也不要忘记方块状态文件,这个用数据生成即可

1
blockStateModelGenerator.registerSimpleState(ModBlocks.SIMPLE_BLOCK);

这里就注册最简单的方块状态即可

而后跑好数据生成之后,我们就可以进入我们的游戏中看看我们的自定义物品和方块了