This commit is contained in:
boybook
2025-12-01 20:59:16 +08:00
parent 12738a142c
commit 760c2dd9ad
5535 changed files with 21070 additions and 2021 deletions

View File

@@ -0,0 +1,138 @@
---
front: https://nie.res.netease.com/r/pic/20211104/69055361-2e7a-452f-8b1a-f23e1262a03a.jpg
hard: 高级
time: 25分钟
---
# 使用Molang增加粒子动感
在本节中我们将通过Snowstorm自带的各种示例来学习如何在粒子中使用Molang。
## 设置变量
![](./images/17.3_loading.png)
我们打开Loading加载粒子来观察如何进行变量设置。
![](./images/17.3_loading_var.png)
在左侧的**Variables****变量**栏中我们可以设置两种Molang变量分别是**Start Variables****起始变量**)和**Tick Variables****滴答变量**)。起始变量是粒子**初始化****Initialize**)时便会设置的变量,只会设置一次。滴答变量是粒子每次跟随游戏滴答主循环进行设置的变量,每游戏刻都会设置一次。
这里,我们设置了两个起始变量`variable.size = 0.08``variable.radius = 0.6`。这在JSON中可以写为
```json
"minecraft:emitter_initialization": {
"creation_expression": "
variable.size = 0.08;
variable.radius = 0.6;
",
"per_update_expression": "" // 没有设置逐更新变量,也就是滴答变量
} // 发射器初始化组件
```
## 动态设置粒子大小
粒子可以通过Molang动态设置大小我们继续看加载粒子的示例。
![](./images/17.3_loading_size.png)
这里使用了先前自定义的变量`variable.size`和一个粒子自带的原生变量`variable.particle_age`。事实上虽然粒子是组件化的但是粒子并不被认为是ECS框架中的一个*实体*。所以,粒子本身并不具备查询函数,粒子所有的查询函数都来自于其挂接的实体。如果粒子挂接的实体消亡,那么粒子也将无法继续使用实体的查询函数。而粒子本身自带的一些变量值皆通过`variable.`前缀来提供。也就是说,虽然粒子没有查询,但是粒子依旧拥有一些原生变量。这里的`variable.particle_age`就是一个例子,它代表粒子从生成带当前为止的时间。
这段内容通过JSON来表示便为
```json
"minecraft:particle_appearance_billboard": {
"size": [
"variable.size*(1-variable.particle_age)",
"variable.size*(1-variable.particle_age)"
],
"facing_camera_mode": "rotate_xyz",
"uv": {
// 纹理UV的相关信息于此处无关
}
},
```
## 动态设置发射器位置
我们可以通过Molang动态设置发射器位置。我们继续看加载粒子。
![](./images/17.3_loading_emitter_shape.png)
我们在发射器的Shape形状栏中可以看到这里用了另一个自定义变量`variable.radius`。这是将后面通过`math.sin``math.cos`构造的单位圆周运动放缩成我们想要的大小。这个圆周运动是对于粒子发射器来说的,也就是说粒子除了上面所说的外观随着粒子年龄而变小之外,还会因为发射器在做圆周运动而在圆周上周期生成。
```json
"minecraft:emitter_shape_point": {
"offset": [
"variable.radius*-math.sin(variable.emitter_age*360)",
"variable.radius*math.cos(variable.emitter_age*360)",
0
]
},
```
接下来我们看另一种粒子的情况。我们来看Magic魔法粒子。
![](./images/17.3_magic.png)
![](./images/17.3_magic_emitter_shape.png)
我们可以看到相对于加载粒子魔法粒子的参数更加丰富。这是因为魔法粒子使用了Disc圆盘形状的发射器。圆盘在数学上一般指一个二维的圆面但是我们的粒子是发射在三维空间中的所以这里的圆盘必须指定一个**法向****Normal**),有了法向我们就可以将圆盘放置在垂直于法向的平面上。法向的方向我们可以用**法向量****Normal Vector**)来表示。**Plane Normal****平面法向**)便是用于指定这个法向量三个轴向分量的属性。
可以看到魔法粒子除了Offset偏移使用了Molang做圆周运动外还在法向量上使用了相同频率的简谐振动。也就是说圆盘所在的平面会在做简谐振动的同时做圆周运动这两个运动的叠加组成了圆盘最终的运动。
## 动态设置粒子自旋
为了和一般的旋转运动(比如上述我们通过圆周运动进行的伪旋转)分开,我们将粒子自身围绕一个轴所做的旋转运动称为**自旋****Spin**)。我们继续来看魔法粒子。
![](./images/17.3_magic_rotate.png)
我们可以看到魔法粒子的单体实例在整体运动的同时还会做自旋运动。这里便通过Molang指定了一个随机的自旋初速度。
## 动态设置粒子线性运动
粒子单体除了自旋,也就是做棱角运动且具有角速度之外,还会做线性运动且具有线速度。我们继续来看魔法粒子。
![](./images/17.3_magic_motion.png)
这里我们发现,我们使用了一个`variable.particle_random_3`变量来进行了线性加速度的随机。事实上,`variable.particle_random_3`是粒子自带的一个原生变量,同样的变量还有`variable.particle_random_1``variable.particle_random_2``variable.particle_random_4``variable.emitter_random_1``variable.emitter_random_2``variable.emitter_random_3``variable.emitter_random_4`。他们分别是0至1之间不同的原生随机变量互不相同可以直接引用。
```json
"minecraft:particle_motion_dynamic": {
"linear_acceleration": [
"math.random(0, 4)",
"math.random(0, 8)",
"variable.particle_random_3>0.2 ? -10 : -4"
]
}
```
## 动态设置粒子碰撞
粒子的碰撞也可以通过Molang控制只不过目前Snowstorm还不支持这一功能。事实上粒子的碰撞即粒子与世界中地形的碰撞是通过`minecraft:particle_motion_collision`组件来实现的虽然Snowstorm的粒子中有一个**Collision****碰撞**栏来支持碰撞参数的修改但是它不支持该组件中唯一支持Molang的`enabled`字段的修改。
```json
"minecraft:particle_motion_collision": {
"enabled": "/* Molang Expression */"
}
```
通过该字段的Molang控制可以动态控制一个粒子是否具备碰撞特性。
## 设计粒子颜色渐变
![](./images/17.3_rainbow.png)
最后我们来通过Rainbow彩虹粒子来学习设置颜色渐变。
![](./images/17.3_rainbow_curve.png)
![](./images/17.3_rainbow_color.png)
彩虹粒子在Color & Light颜色和光照栏中将**Color Mode****配色模式**)更改为了**Gradient****渐变**),并使用了**Interpolant****插值**)变量`variable.rainbow`。而可以看到,在最上部的**Curve****曲线**)栏中,我们定义了变量`variable.rainbow`的曲线。它使用`variable.particle_random_2`原生变量作为**Input****输入**)变量,通过**Catmull-Rom插值**产生了一个曲线,从而产生了预览窗中显示的彩虹效果。
至此我们基本了解了Molang在粒子中的应用。事实上在Snowstorm的菜单栏中我们可以获取到所有粒子的原生Molang变量的信息以供后续制作参考
![](./images/17.3_molang_ref.png)
![](./images/17.3_molangs.png)