我们本次尝试在1.19.2 Fabric中添加一个能够具有各种动画效果动作的生物实体。
效果展示 效果展示 效果展示
1.首先,为了实现这些动画效果,我们需要首先使用到一个模组:geckolib(下载地址)
找到项目的build.gradle
文件,在repositories
和dependencies
中添加依赖。
repositories {
//添加这个
maven { url 'https://dl.cloudsmith.io/public/geckolib3/geckolib/maven/' }
}
dependencies {
minecraft 'net.minecraftforge:forge:1.19.2-43.1.1'
//添加这个
modImplementation 'software.bernie.geckolib:geckolib-fabric-1.19:3.1.18'
}
之后点击Refresh Gradle Project按钮重新构建项目
构建好了项目后在项目的ModMain类中添加一句geckolib的初始化语句:
ModMain.java
@Override
public void onInitialize() {
ItemInit.registerModItems();
//添加这个
GeckoLib.initialize();
}
2.之后,与之前的教程一样,我们需要在blockbench中制作一个模组中的生物实体:
进入软件后我们要找到一个插件按钮,然后再搜索栏中输入GeckoLib Animation Utils
,并下载这个插件
将我们制作好的生物实体进行模型转换工作,找到Convert Project
,之后选择Geckolib Animated Model
在这之后,你会发现你的生物实体栏多了一个Animate栏
,点击进去:
具体动作制作的视频:Blockbench动画制作
在制作好所有的动画后我们导出模型和动画json文件。
3.模型制作完成,接下来需要制作生物实体类,因为我们的生物的动作有很多,所以要在生物的不同状态时做出对应的动作。
EntityGoose.json
package net.joy187.joyggd.entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.ai.goal.LookAroundGoal;
import net.minecraft.entity.ai.goal.SwimGoal;
import net.minecraft.entity.ai.goal.WanderAroundFarGoal;
import net.minecraft.entity.attribute.DefaultAttributeContainer;
import net.minecraft.entity.attribute.EntityAttributes;
import net.minecraft.entity.mob.MobEntity;
import net.minecraft.entity.passive.ChickenEntity;
import net.minecraft.world.World;
import software.bernie.geckolib3.core.IAnimatable;
import software.bernie.geckolib3.core.PlayState;
import software.bernie.geckolib3.core.builder.AnimationBuilder;
import software.bernie.geckolib3.core.controller.AnimationController;
import software.bernie.geckolib3.core.event.predicate.AnimationEvent;
import software.bernie.geckolib3.core.manager.AnimationData;
import software.bernie.geckolib3.core.manager.AnimationFactory;
public class EntityGoose extends ChickenEntity implements IAnimatable {
private AnimationFactory factory = new AnimationFactory(this);
public EntityGoose(EntityType<? extends ChickenEntity> entityType, World world) {
super(entityType, world);
// TODO Auto-generated constructor stub
}
//生物ai
@Override
protected void initGoals() {
this.goalSelector.add(1, new SwimGoal(this));
this.goalSelector.add(3, new WanderAroundFarGoal(this, 0.75f, 1));
this.goalSelector.add(4, new LookAroundGoal(this));
}
//生物一些属性
public static DefaultAttributeContainer.Builder setAttributes() {
return MobEntity.createMobAttributes()
.add(EntityAttributes.GENERIC_MAX_HEALTH, 10.0D)
.add(EntityAttributes.GENERIC_MOVEMENT_SPEED, 0.15f);
}
//生物动作状态机
private <E extends IAnimatable> PlayState predicate(AnimationEvent<E> event) {
//在空中时播放摔落动画
if(!this.onGround){
event.getController().setAnimation(new AnimationBuilder().addAnimation("animation.goose.fall", true));
return PlayState.CONTINUE;
}
//移动时播放走路动画
if (event.isMoving()) {
event.getController().setAnimation(new AnimationBuilder().addAnimation("animation.goose.walk", true));
return PlayState.CONTINUE;
}
//平时播放发呆动画
event.getController().setAnimation(new AnimationBuilder().addAnimation("animation.goose.idle", true));
return PlayState.CONTINUE;
}
//将状态机进行注册
@Override
public void registerControllers(AnimationData data) {
data.addAnimationController(new AnimationController<EntityGoose>(this, "controller",
0, this::predicate));
}
@Override
public AnimationFactory getFactory() {
return factory;
}
}
4.新建生物实体模型文件ModelGoose类:
ModelGoose.java
package net.joy187.joyggd.entity.model;
import net.joy187.joyggd.ModMain;
import net.joy187.joyggd.entity.EntityGoose;
import net.minecraft.util.Identifier;
import software.bernie.geckolib3.model.AnimatedGeoModel;
public class ModelGoose extends AnimatedGeoModel<EntityGoose> {
//模型文件地址
@Override
public Identifier getModelResource(EntityGoose object) {
return new Identifier(ModMain.MOD_ID, "geo/goose.geo.json");
}
//皮肤贴图文件地址
@Override
public Identifier getTextureResource(EntityGoose object) {
return new Identifier(ModMain.MOD_ID, "textures/entity/goose.png");
}
//动画文件地址
@Override
public Identifier getAnimationResource(EntityGoose animatable) {
return new Identifier(ModMain.MOD_ID, "animations/goose.animation.json");
}
}
5.模型部分结束,开始着手渲染类的编写。新建RenderGoose类。
RenderGoose.java
package net.joy187.joyggd.entity.render;
import net.joy187.joyggd.ModMain;
import net.joy187.joyggd.entity.EntityGoose;
import net.joy187.joyggd.entity.model.ModelGoose;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.entity.EntityRendererFactory;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.util.Identifier;
import software.bernie.geckolib3.renderers.geo.GeoEntityRenderer;
public class RenderGoose extends GeoEntityRenderer<EntityGoose> {
public RenderGoose(EntityRendererFactory.Context ctx) {
super(ctx, new ModelGoose());
this.shadowRadius = 0.4f;
}
//贴图文件地址
@Override
public Identifier getTextureResource(EntityGoose instance) {
return new Identifier(ModMain.MOD_ID, "textures/entity/goose.png");
}
@Override
public RenderLayer getRenderType(EntityGoose animatable, float partialTicks, MatrixStack stack,
VertexConsumerProvider renderTypeBuffer, VertexConsumer vertexBuilder,
int packedLightIn, Identifier textureLocation) {
//让你的生物体型放大多少倍(x,y,z三个方向)
stack.scale(1f, 1f, 1f);
return super.getRenderType(animatable, partialTicks, stack, renderTypeBuffer, vertexBuilder, packedLightIn, textureLocation);
}
}
6.在EntityInit.java
中注册我们生物信息:
EntityInit.java
package net.joy187.joyggd.init;
import net.fabricmc.fabric.api.object.builder.v1.entity.FabricEntityTypeBuilder;
import net.joy187.joyggd.ModMain;
import net.joy187.joyggd.entity.EntityGoose;
import net.minecraft.entity.EntityDimensions;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.SpawnGroup;
import net.minecraft.util.Identifier;
import net.minecraft.util.registry.Registry;
public class EntityInit {
public static final EntityType<EntityGoose> GOOSE = Registry.register(
Registry.ENTITY_TYPE, new Identifier(ModMain.MOD_ID, "goose"), //你的modid,生物名称
FabricEntityTypeBuilder.create(SpawnGroup.CREATURE, EntityGoose::new) //我们的生物属于CREATURE型
.dimensions(EntityDimensions.fixed(0.6F, 1.5F)).build()); //EntityDimensions用于设置碰撞箱大小
}
在ModClient.java
中添加我们的模型渲染注册语句:
ModClient.java
package net.joy187.joyggd;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.client.rendering.v1.EntityRendererRegistry;
import net.joy187.joyggd.entity.render.RenderGoose;
import net.joy187.joyggd.init.EntityInit;
public class ModClient implements ClientModInitializer{
@Override
public void onInitializeClient() {
//添加渲染注册语句 第一个是我们的生物,第二个是渲染文件
EntityRendererRegistry.register(EntityInit.GOOSE, RenderGoose::new);
}
}
在项目主类ModMain中添加生物属性注册语句:
ModMain.java
package net.joy187.joyggd;
public class ModMain implements ModInitializer {
public static final String MOD_ID = "joyggd";
public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID);
public static final ItemGroup ITEMTAB = FabricItemGroupBuilder.build(
new Identifier(MOD_ID, "itemtab"), () -> new ItemStack(ItemInit.SHERIFF));
@Override
public void onInitialize() {
ItemInit.registerModItems();
GeckoLib.initialize();
//添加生物属性注册语句
FabricDefaultAttributeRegistry.register(EntityInit.GOOSE, EntityGoose.setAttributes());
}
}
7.生物实体部分结束,接下来我们要给生物制作一个刷怪蛋:
在ItemInit类中添加我们的刷怪蛋物品:
//SpawnEggItem参数:生成的生物,刷怪蛋主颜色,刷怪蛋副颜色,放在哪个物品栏中
public static final Item GOOSE_SPAWN_EGG = registerItem("goose_spawn_egg",
new SpawnEggItem(EntityInit.GOOSE,0x22b341, 0x19732e,
new FabricItemSettings().group(ModMain.ITEMTAB)));
8.代码部分结束,来到资源包制作环节
在resources\assets\你的modid
中的lang包中的en_us.json
添加刷怪蛋和生物实体英文名称:
"item.joyggd.goose_spawn_egg": "Mob Spawn Egg",
"entity.joyggd.goose": "Mob",
在models\item
包中添加刷怪蛋模型文件:
goose_spawn_egg.json
{
"parent": "item/template_spawn_egg"
}
在textures\entity
中添加生物实体的皮肤贴图
新建一个geo包和animation包,把第二步中的模型和动画文件分别放进去
9.最后我们还要给这个生物设定其掉落物
在resources\data\你的modid
中新建loot_tables
包-> loot_tables
包中新建entities
包 -> entities
包中新建我们的战利品文件goose.json
:
战利品文件中name
为物品名称,weight
为掉落权重,越大掉这个物品的概率越高,count
为掉落个数,min
为最小掉几个,max
为最大掉几个。
goose.json
{
"pools": [
{
"rolls": 1.0,
"bonus_rolls": 0.0,
"entries": [
{
"type": "item",
"name": "joyggd:lei",
"weight": 5,
"functions": [
{
"function": "set_count",
"count": {
"min": 1,
"max": 3
}
},
{
"function": "looting_enchant",
"count": {
"min": 0,
"max": 1
}
}
]
},
{
"type": "item",
"weight": 10,
"name": "minecraft:iron_nugget",
"functions": [
{
"function": "set_count",
"count": {
"min": 2,
"max": 3
}
}
]
},
{
"type": "item",
"weight": 10,
"name": "minecraft:rotten_flesh",
"functions": [
{
"function": "set_count",
"count": {
"min": 0,
"max": 2
}
}
]
},
{
"type": "item",
"weight": 5,
"name": "joyggd:blacksheephead",
"functions": [
{
"function": "set_count",
"count": {
"min": 0,
"max": 2
}
}
]
}
]
}
]
}