粒子光环制作
参考 http://i-remember.fr/en 这类网站,使用粒子流编程控制制作一些效果, 如“粒子光环”
在本次作业中,我使用粒子系统制作了一个彩虹效果的烟花。
基本步骤
首先,新建一个空对象Halo,并添加子对象,然后加入粒子系统:
然后新建脚本Halo,在脚本中完成具体粒子效果的实现。
private ParticleSystem particleSys; // 粒子系统
private ParticleSystem.Particle[] particleArr; // 粒子数组
private ParticleInfo[] particles; // 粒子位置数组
public Gradient colorGradient; // 粒子颜色改变器
public int count = 10000; // 粒子数量
public float size = 0.03f; // 粒子大小
public float minRadius = 5.0f; // 最小半径
public float maxRadius = 12.0f; // 最大半径
public bool clockwise = true; // 顺时针|逆时针
public float speed = 2f; // 速度
public float pingPong = 0.02f; // 游离范围
首先在Halo中声明需要用到的相关变量,包括了粒子系统、数组、位置数组以及粒子的数量、大小和半径范围等参数。
public class ParticleInfo
{
public float radius = 0f, angle = 0f, time = 0f;
public ParticleInfo(float x, float y, float z)
{
radius = x;
angle = y;
time = z;
}
}
ParticleInfo类定义了每个粒子的半径、角度和时间,方便之后的处理。
void RandomlySpread()
{
for (int i = 0; i < count; i ++)
{
// 随机粒子距离中心的半径
float midR = (maxRadius + minRadius) / 2;
float minRate = Random.Range(1, midR / minRadius);
float maxRate = Random.Range(midR / maxRadius, 1);
float R = Random.Range(minRadius * minRate, maxRadius * maxRate);
// 随机每个粒子的角度
float angle = Random.Range(0, 360);
float theta = angle / 180 * Mathf.PI;
// 随机每个粒子的游离起始时间
float time = Random.Range(0.0f, 360.0f);
particles[i] = new ParticleInfo(R, angle, time);
particleArr[i].position = new Vector3(particles[i].radius * Mathf.Cos(theta), 0f, particles[i].radius * Mathf.Sin(theta));
}
particleSys.SetParticles(particleArr, particleArr.Length);
}
RandomlySpread函数用来赋予每个粒子一个初始的位置,在一定范围内随机生成每个粒子的位置、角度游离时间。我们希望粒子总体集中在平均半径附近,这样看起来比较美观。
// Start is called before the first frame update
void Start()
{
//initialize
particleArr = new ParticleSystem.Particle[count];
particles = new ParticleInfo[count];
// 初始化粒子系统
particleSys = this.GetComponent<ParticleSystem>();
particleSys.startSpeed = 0; // 粒子位置由程序控制
particleSys.startSize = size; // 设置粒子大小
particleSys.loop = false;
particleSys.maxParticles = count; // 设置最大粒子量
particleSys.Emit(count); // 发射粒子
particleSys.GetParticles(particleArr);
RandomlySpread(); // 初始化各粒子位置
}
Start中初始化粒子数组和粒子系统,并初始化粒子的位置(调用RandomlySpread函数)。
void Update()
{
for (int i = 0; i < count; i++)
{
if (clockwise)
particles[i].angle -= (i % tier + 1) * (speed / particles[i].radius / tier);
else
particles[i].angle += (i % tier + 1) * (speed / particles[i].radius / tier);
particles[i].angle = (360.0f + particles[i].angle) % 360.0f;
float theta = particles[i].angle / 180 * Mathf.PI;
float x = 10 * Mathf.Sin(8 * theta) * Mathf.Cos(theta);
float y = 10 * Mathf.Sin(8 * theta) * Mathf.Sin(theta);
particleArr[i].position = new Vector3(x, 0f, y + Random.Range(-1f, 1f));
// 粒子在半径方向上游离
particles[i].time += Time.deltaTime;
particles[i].radius += Mathf.PingPong(particles[i].time / minRadius / maxRadius, pingPong) - pingPong / 2.0f;
//改变粒子透明度
particleArr[i].color = colorGradient.Evaluate(Random.value);
}
particleSys.SetParticles(particleArr, particleArr.Length);
}
Update函数用来更新粒子的位置,首先通过设置一个差分层变量tier将粒子系统分为十层,每一层角度的增量都不相同,这就使得粒子系统的运动更加美观。clockwise决定旋转的方向。由于总体是圆形,所以要保证粒子的角度在0-360度之间。此外,还有一个PingPong函数,使得粒子在一个半径范围内来回地波动。
为了使粒子系统呈现烟花的形状。我在这里使用了玫瑰线函数,该函数图像及参数方程如下:
r = 10
x = rsin(10t)cos(t)
y = rsin(10*t)*sin(t)
可以通过调整数值来改变叶片的数量。
通过将粒子数组的position设置为该函数来使得粒子系统呈现烟花状:
float theta = particles[i].angle / 180 * Mathf.PI;
float x = 10 * Mathf.Sin(8 * theta) * Mathf.Cos(theta);
float y = 10 * Mathf.Sin(8 * theta) * Mathf.Sin(theta);
particleArr[i].position = new Vector3(x, 0f, y + Random.Range(-1f, 1f));
最后,创建三个粒子系统,并分别加上红黄蓝三种颜色,将它们叠加在一起,最后就可以看到一个彩虹色的烟花了: