对于每一个需要生成模型的物品,我们必须创建两个独立的 JSON 文件:
- 一个物品模型,用于定义物品的纹理、旋转和整体外观。 将生成在
generated/assets/example-mod/models/item目录下。 - 一个客户端物品,根据组件、交互等不同标准来定义使用的模型。 将生成在
generated/assets/example-mod/items目录下。
设置
首先,我们需要创建 ModelProvider。
TIP
可以重新使用在方块模型生成中创建的 FabricModelProvider。
创建一个继承 FabricModelProvider 的类,并且实现两个抽象方法:generateBlockStateModels 和 generateItemModels。 然后,创建一个匹配 super 的构造器。
java
public class ExampleModModelProvider extends FabricModelProvider {
public ExampleModModelProvider(FabricDataOutput output) {
super(output);
}
@Override
public void generateBlockStateModels(BlockModelGenerators blockStateModelGenerator) {
}
@Override
public void generateItemModels(ItemModelGenerators itemModelGenerator) {
}
@Override
public String getName() {
return "ExampleModModelProvider";
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
接着在 DataGeneratorEntrypoint 入口点的 onInitializeDataGenerator 方法里注册这个类。
java
pack.addProvider(ExampleModModelProvider::new);1
内置物品模型
对于物品模型,我们将使用 generateItemModels 方法, 其形参 ItemModelGenerators itemModelGenerator 负责生成物品模型,并包含相应的方法。
以下是最常用的物品模型生成方法。
简单
简单物品模型即是默认的模型,也是大多数原版物品所使用的模型, 其父模型为 GENERATED, 在背包中使用 2D 纹理,但在游戏中渲染为 3D, 例如船、蜡烛和染料。
java
itemModelGenerator.generateFlatItem(ModItems.RUBY, ModelTemplates.FLAT_ITEM);1
手持
手持物品通常用于工具和武器(斧、剑、三叉戟)。 这些物品的旋转和定位与简单模型有点区别,从而在手中看上去更自然。
java
itemModelGenerator.generateFlatItem(ModItems.GUIDITE_AXE, ModelTemplates.FLAT_HANDHELD_ITEM);1
可染色
可染色物品的方法会生成一个简单的物品模型和客户端物品,并会指定着色(tint)颜色。 此方法需要一个默认的十进制颜色值,用于未染色的物品。 皮革的默认值为 0xFFA06540。
java
itemModelGenerator.generateDyedItem(ModItems.LEATHER_GLOVES, 0xFFA06540);1
重要
需要将物品添加到 ItemTags.DYEABLE 标签,才能在物品栏中染色!
条件
接下来,我们来尝试生成会在当由第二个参数 BooleanProperty 指定的特定条件满足时改变其外观的物品模型。 这是其中的一些:
| 属性 | 描述 |
|---|---|
IsKeybindDown | 当特定按键按下时为 true。 |
IsUsingItem | 当物品被使用时为 true(例如用盾牌格挡)。 |
Broken | 当物品的耐久为 0 时为 true(例如鞘翅被破坏时改变纹理)。 |
HasComponent | 当物品拥有特定的组件时为 true。 |
第 3 和第 4 个参数,分别是在属性为 true 和 false 时使用的模型。
java
itemModelGenerator.generateBooleanDispatch(
ModItems.FLASHLIGHT,
ItemModelUtils.isUsingItem(),
ItemModelUtils.plainModel(itemModelGenerator.createFlatItemModel(ModItems.FLASHLIGHT, "_lit", ModelTemplates.FLAT_ITEM)),
ItemModelUtils.plainModel(itemModelGenerator.createFlatItemModel(ModItems.FLASHLIGHT, ModelTemplates.FLAT_ITEM))
);1
2
3
4
5
6
2
3
4
5
6
重要
要获得传入 ItemModelUtils.plainModel() 的 Identifier,始终使用 itemModelGenerator.createFlatItemModel(),否则只会生成客户端物品,而不是物品模型!
复合
复合物品模型会由一个或更多个纹理层叠组成。 这个没有原版的方法,你需要使用 itemModelGenerator 的 itemModelOutput 字段,然后调用 accept()。
java
ItemModel.Unbaked hoe = ItemModelUtils.plainModel(itemModelGenerator.createFlatItemModel(ModItems.ENHANCED_HOE, ModelTemplates.FLAT_ITEM));
ItemModel.Unbaked hoePlus = ItemModelUtils.plainModel(itemModelGenerator.createFlatItemModel(ModItems.ENHANCED_HOE, "_plus", ModelTemplates.FLAT_ITEM));
itemModelGenerator.itemModelOutput.accept(
ModItems.ENHANCED_HOE,
ItemModelUtils.composite(hoe, hoePlus)
);1
2
3
4
5
6
7
2
3
4
5
6
7
选择
基于特定属性的值渲染物品模型。 有这样一些:
| 属性 | 描述 |
|---|---|
ContextDimension | 基于玩家所在的维度渲染物品模型(主世界、下界、末地)。 |
MainHand | 当物品装备在玩家的主手时渲染物品模型。 |
DisplayContext | 基于物品所在的地方渲染物品模型(ground:地面,fixed:固定在物品展示框中,hand:手上…)。 |
ContextEntityType | 基于持有物品的实体渲染物品模型。 |
在此例中,物品会在不同维度时改变纹理:在主世界是绿的,下界是红的,末地是黑的。
java
ItemModel.Unbaked crystalOverworld = ItemModelUtils.plainModel(itemModelGenerator.createFlatItemModel(ModItems.DIMENSIONAL_CRYSTAL, "_overworld", ModelTemplates.FLAT_ITEM));
ItemModel.Unbaked crystalNether = ItemModelUtils.plainModel(itemModelGenerator.createFlatItemModel(ModItems.DIMENSIONAL_CRYSTAL, "_nether", ModelTemplates.FLAT_ITEM));
ItemModel.Unbaked crystalEnd = ItemModelUtils.plainModel(itemModelGenerator.createFlatItemModel(ModItems.DIMENSIONAL_CRYSTAL, "_end", ModelTemplates.FLAT_ITEM));
itemModelGenerator.itemModelOutput.accept(
ModItems.DIMENSIONAL_CRYSTAL,
ItemModelUtils.select(new ContextDimension(),
ItemModelUtils.when(Level.OVERWORLD, crystalOverworld),
ItemModelUtils.when(Level.NETHER, crystalNether),
ItemModelUtils.when(Level.END, crystalEnd)
)
);1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
范围派发
基于数字属性的值渲染物品模型。 接收一个物品和变种列表,每个都与值配对。 示例包括指南针、弓和刷子。
有不少支持的属性,这里是一些例子:
| 属性 | 描述 |
|---|---|
Cooldown | 基于物品的剩余冷却时间渲染物品模型。 |
Count | 基于物品堆的大小渲染物品模型。 |
UseDuration | 基于物品使用了多久渲染物品模型。 |
Damage | 基于攻击伤害渲染物品模型(minecraft:damage 组件)。 |
这是个使用 Count 的例子,纹理从一个刀改变为三个,基于物品堆的大小。
java
ItemModel.Unbaked knifeOne = ItemModelUtils.plainModel(itemModelGenerator.createFlatItemModel(ModItems.THROWING_KNIVES, "_one", ModelTemplates.FLAT_ITEM));
ItemModel.Unbaked knifeTwo = ItemModelUtils.plainModel(itemModelGenerator.createFlatItemModel(ModItems.THROWING_KNIVES, "_two", ModelTemplates.FLAT_ITEM));
ItemModel.Unbaked knifeThree = ItemModelUtils.plainModel(itemModelGenerator.createFlatItemModel(ModItems.THROWING_KNIVES, "_three", ModelTemplates.FLAT_ITEM));
itemModelGenerator.itemModelOutput.accept(
ModItems.THROWING_KNIVES,
ItemModelUtils.rangeSelect(
new Count(false),
List.of(
ItemModelUtils.override(knifeOne, 1.0F),
ItemModelUtils.override(knifeTwo, 2.0F),
ItemModelUtils.override(knifeThree, 3.0F)
)
)
);1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
自定义物品模型
生成物品模型不仅可以通过原版方法完成,你当然还可以创建自己的。 在本段中,我们会为一个气球物品创建自定义的模型。
本教程此部分的所有字段和模型都声明在叫做 CustomItemModelGenerator 的静态内部类中。
显示 CustomItemModelGenerator
java
public static class CustomItemModelGenerator {
//:::custom-item-model:::
public static final ModelTemplate SCALED2X = item("scaled2x", TextureSlot.LAYER0);
//:::custom-item-model:::
//:::custom-item-datagen-method
public static void registerScaled2x(Item item, ItemModelGenerators generator) {
Identifier itemModel = SCALED2X.create(item, TextureMapping.singleSlot(TextureSlot.LAYER0, ModelLocationUtils.getModelLocation(item)), generator.modelOutput);
generator.itemModelOutput.accept(item, ItemModelUtils.plainModel(itemModel));
}
//:::custom-item-datagen-method
@SuppressWarnings("SameParameterValue")
//:::custom-item-model:::
private static ModelTemplate item(String parent, TextureSlot requiredTextureKeys) {
return new ModelTemplate(Optional.of(Identifier.fromNamespaceAndPath(ExampleMod.MOD_ID, "item/" + parent)), Optional.empty(), requiredTextureKeys);
}
//:::custom-item-model:::
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
创建自定义父模型
首先,先创建一个父物品模型,定义物品在游戏内如何显示。 比如说,我们要让气球看上去像普通的物品模型,但放大。
要做到这个,我们先创建 resources/assets/example-mod/models/item/scaled2x.json,将其父模型设置为 item/generated 模型,然后覆盖缩放。
json
{
"parent": "item/generated",
"display": {
"ground": {
"rotation": [0, 0, 0],
"translation": [0, 2, 0],
"scale": [1, 1, 1]
},
"head": {
"rotation": [0, 180, 0],
"translation": [0, 13, 7],
"scale": [2, 2, 2]
},
"thirdperson_righthand": {
"rotation": [0, 0, 0],
"translation": [0, 3, 1],
"scale": [1.1, 1.1, 1.1]
},
"firstperson_righthand": {
"rotation": [0, -90, 25],
"translation": [1.13, 3.2, 1.13],
"scale": [1.36, 1.36, 1.36]
}
}
}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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
这会使模型看上去有普通物品的两倍大小。
创建 ModelTemplate
接下来我们需要创建 ModelTemplate 类的实例, 代表我们模组内部的实际父物品模型。
java
public static final ModelTemplate SCALED2X = item("scaled2x", TextureSlot.LAYER0);
private static ModelTemplate item(String parent, TextureSlot requiredTextureKeys) {
return new ModelTemplate(Optional.of(Identifier.fromNamespaceAndPath(ExampleMod.MOD_ID, "item/" + parent)), Optional.empty(), requiredTextureKeys);
}1
2
3
4
5
6
2
3
4
5
6
item() 方法会创建新的 ModelTemplate 实例,指向我们刚刚创建的 scaled2x.json 文件。
TextureSlot LAYER0 代表 #layer0 纹理变量,会被指向纹理的 ID 替代。
添加自定义数据生成方法
最后一步是创建自定义方法,会在 generateItemModels() 中调用,我们在此需要创建自己的物品模型。
java
public static void registerScaled2x(Item item, ItemModelGenerators generator) {
Identifier itemModel = SCALED2X.create(item, TextureMapping.singleSlot(TextureSlot.LAYER0, ModelLocationUtils.getModelLocation(item)), generator.modelOutput);
generator.itemModelOutput.accept(item, ItemModelUtils.plainModel(itemModel));
}1
2
3
4
5
2
3
4
5
我们看看参数是做什么的:
Item item:物品,为此物品生成模型。ItemModelGenerators generator:和传入generateItemModels()的相同。 用于其字段。
首先,先使用 SCALED2X.create() 得到 Identifier,从我们的 generator 参数传入一个 TextureMapping 和 modelOutput。
然后,使用其字段的另一个,itemModelOutput(本质上用作一个 consumer),并使用 accept() 方法,从而让模型实际生成。
调用自定义方法
现在,我们只需要在 generateItemModels() 方法中调用我们的方法。
java
CustomItemModelGenerator.registerScaled2x(ModItems.BALLOON, itemModelGenerator);1
不要忘记添加纹理文件!
来源和链接
你可以查看 Fabric API 中的示例测试和此文档的示例模组以获取更多信息。





