场景:

​ Fabric官方自定义粒子教程生成的粒子太过单调,仅仅只是教会你自定义纹理贴图?这一点都不合理。而本教程旨在能够给粒子添加更多的属性,并且能够在游戏运行时创建含有特定数据的粒子,比如粒子的生命周期❤️!

准备:

​ 需要的几个类(按照自己习惯取名):

1
2
3
CustomPtcEffect.java【自定义粒子效果(拿来传递参数的)】
CustomPtc.java 【自定义的粒子,这个类主要拿来使用参数的】
然后就是一些其它需要你注册粒子的地方。

​ 如果你需要熟练掌握,那么你还得了解一些CODEC(序列化)的知识。

开始:

​ 经过前面的准备,以及可以开始了🚙!

一,编写主要类

CustomPtcEffect.java
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
/**
* 自定义粒子效果类,实现了ParticleEffect接口
* 该类用于定义一个具有自定义生命周期的粒子效果
*/
public class CustomPtcEffect implements ParticleEffect {
// 自定义粒子效果的PacketCodec,用于粒子效果的序列化和反序列化
public static final PacketCodec<ByteBuf, CustomPtcEffect> PACKET_CODEC = PacketCodec.of(
(val, buf) -> {
buf.writeInt(val.lifeTick);
},
buf -> new CustomPtcEffect(null, buf.readInt())
);
// 粒子生命周期的Codec,用于粒子生命周期的编解码
private static final Codec<Integer> TICK_CODEC = Codec.INT;
// 粒子类型
private final ParticleType<CustomPtcEffect> type;
// 粒子的生命周期,以tick为单位
private final Integer lifeTick;
/**
* 构造函数,初始化自定义粒子效果
*
* @param type 粒子类型
* @param lifeTick 粒子的生命周期,以tick为单位
*/
public CustomPtcEffect(ParticleType<CustomPtcEffect> type, Integer lifeTick) {
this.type = type;
this.lifeTick = lifeTick;
}
/**
* 创建自定义粒子效果的MapCodec
*
* @param type 粒子类型
* @return 自定义粒子效果的MapCodec
*/
public static MapCodec<CustomPtcEffect> createCodec(ParticleType<CustomPtcEffect> type) {
return TICK_CODEC.<CustomPtcEffect>xmap(t -> new CustomPtcEffect(type, t), ptcEffect -> ptcEffect.lifeTick).fieldOf("tick");
}
/**
* 创建自定义粒子效果的PacketCodec
*
* @param type 粒子类型
* @return 自定义粒子效果的PacketCodec
*/
public static PacketCodec<? super ByteBuf, CustomPtcEffect> createPacketCodec(ParticleType<CustomPtcEffect> type) {
return PACKET_CODEC.xmap(t -> new CustomPtcEffect(type, t.lifeTick), ptcEffect -> ptcEffect);
}
/**
* 获取粒子类型
*
* @return 粒子类型
*/
@Override
public ParticleType<CustomPtcEffect> getType() {
return this.type;
}
/**
* 获取粒子的生命周期
*
* @return 粒子的生命周期,以tick为单位
*/
public Integer getLifeTick() {
return this.lifeTick;
}
}
CustomPtc.java
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
/**
* 自定义粒子类,继承自SpriteBillboardParticle,用于实现特定的粒子效果
*/
public class CustomPtc extends SpriteBillboardParticle {
// 自定义粒子效果的参数
private final CustomPtcEffect parameters;
// 粒子的精灵提供者
private final SpriteProvider sprite;
/**
* 构造函数,初始化自定义粒子
*
* @param clientWorld 粒子所在的世界
* @param d 粒子的x坐标
* @param e 粒子的y坐标
* @param f 粒子的z坐标
* @param parameters 自定义粒子效果的参数
* @param sprite 粒子的精灵提供者
*/
protected CustomPtc(ClientWorld clientWorld, double d, double e, double f, CustomPtcEffect parameters, SpriteProvider sprite) {
super(clientWorld, d, e, f);
this.parameters = parameters;
this.sprite = sprite;
// 设置粒子的最大存活时间
this.setMaxAge(parameters.getLifeTick());
// 设置粒子的精灵
this.setSprite(sprite);
}
/**
* 获取粒子纹理图的类型
*
* @return 粒子纹理图的类型为不透明类型
*/
@Override
public ParticleTextureSheet getType() {
return ParticleTextureSheet.PARTICLE_SHEET_OPAQUE;
}
/**
* 粒子工厂类,用于创建自定义粒子
*/
@Environment(EnvType.CLIENT)
public static class Factory implements ParticleFactory<CustomPtcEffect> {
// 粒子的精灵提供者
private final SpriteProvider spriteProvider;

/**
* 构造函数,初始化粒子工厂
*
* @param spriteProvider 粒子的精灵提供者
*/
public Factory(SpriteProvider spriteProvider) {
this.spriteProvider = spriteProvider;
}
/**
* 创建自定义粒子
*
* @param effect 粒子效果的参数
* @param clientWorld 粒子所在的世界
* @param d 粒子的x坐标
* @param e 粒子的y坐标
* @param f 粒子的z坐标
* @param g 粒子的x轴速度
* @param h 粒子的y轴速度
* @param i 粒子的z轴速度
* @return 创建的自定义粒子实例
*/
public Particle createParticle(CustomPtcEffect effect, ClientWorld clientWorld, double d, double e, double f, double g, double h, double i) {
return new CustomPtc(clientWorld, d, e, f, effect, this.spriteProvider);
}
}
}

二,注册:

​ 刚才已经完成了类的编写,那么现在来注册这它们吧!

1,注册服务端粒子效果类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 服务端注册效果类
public static final ParticleType<CustomPtcEffect> CUSTOM_PTC_EFFECT = register("custom_ptc_effect", true, CustomPtcEffect::createCodec, CustomPtcEffect::createPacketCodec);
// 下面这段代码来自原版
private static <T extends ParticleEffect> ParticleType<T> register(
String name,
boolean alwaysShow,
Function<ParticleType<T>, MapCodec<T>> codecGetter,
Function<ParticleType<T>, PacketCodec<? super RegistryByteBuf, T>> packetCodecGetter
) {
return Registry.register(Registries.PARTICLE_TYPE, Identifier.of(MOD_ID,name), new ParticleType<T>(alwaysShow) {
@Override
public MapCodec<T> getCodec() {
return codecGetter.apply(this);
}
@Override
public PacketCodec<? super RegistryByteBuf, T> getPacketCodec() {
return packetCodecGetter.apply(this);
}
});
}
2,注册客户端粒子类

​ 这里很简单!

1
ParticleFactoryRegistry.getInstance().register(TrParticle.CUSTOM_PTC_EFFECT, CustomPtc.Factory::new);

三,提示(使用):

​ 该方法注册的粒子不能通过指令生成,只能在代码里面生成,就像这样⬇️:

1
world.addParticle(new CustomPtcEffect(TrParticle.CUSTOM_PTC_EFFECT,15),pos.x,pos.y,pos.z,0,0,0);

踩坑: