天天看点

粒子效果(Lab 9)

阅读“Unity制作神奇的粒子海洋!” 点击打开链接

参考点击打开链接制作类似该网站的效果。

该参考网站的粒子效果:

粒子效果(Lab 9)

于是,我们的目标就是利用Unity实现相似的粒子效果。

我们可以观察到:

1. 粒子的分布主要是一个环状;

2. 粒子的明暗分布是不均匀的;

3. 粒子的运动轨迹是顺时针和逆时针混合的;

4. 粒子并没有一个严格的圆形运动轨迹,每个粒子几乎都是散乱的随其他粒子一起,做圆形运动。

于是,我们可以考虑在一个空对象下,建立我们的粒子系统,并利用程序来控制粒子运动。

步骤一

创建空对象,在该对象中添加组件->Effect->Particle System

粒子效果(Lab 9)

步骤二

创建C#文件CirclePosition,来记录粒子运动轨迹的半径,目前运动的角度,以及运动的时间。

public class CirclePosition {

	public float radius = 0f, angle = 0f, time = 0f;  
	public CirclePosition(float radius, float angle, float time) {  
		this.radius = radius;   // 运动轨迹的半径 
		this.angle = angle;     // 粒子当前运动位置的角度  
		this.time = time;       // 时间  
	}
}
           

步骤三

接下来就是粒子运动的关键部分,创建C#文件Particle,来控制粒子的各项信息,包括大小,数量,运动速度,运动方向等 我们以实现顺时针方向运动的粒子运动为例,首先,我们利用公有变量来设置粒子的大小、半径等基本信息:

private ParticleSystem particleSystem;  // 粒子系统
	private ParticleSystem.Particle[] Arrye;  // 粒子数组
	private CirclePosition[] circlePosition;

	public int count = 10000;       // 粒子数量
	public float size = 0.05f;      // 粒子大小
	public float minRadius = 5.0f;  // 粒子旋转最小半径
	public float maxRadius = 10.0f; // 粒子旋转最大半径
	public float speed = 2f;        // 速度
           

初始化之后,我们需要随机分布这些粒子:

void ParticleRandom() {  
	for (int i = 0; i < count; ++i) {
		// 随机设置每个粒子的运动轨迹半径,同时保证粒子在带状分布的范围内,中间多,两边少
		float midRadius = (maxRadius + minRadius) / 2;  
		float minRate = Random.Range(1.0f, midRadius / minRadius);  
		float maxRate = Random.Range(midRadius / maxRadius, 1.0f);  
		float radius = Random.Range(minRadius * minRate, maxRadius * maxRate);  

		// 在0-360°之间随机分配每个粒子的角度
		float angle = Random.Range(0.0f, 360.0f);

		// 随机每个粒子的游离起始时间
		float time = Random.Range(0.0f, 60.0f);

		circlePosition[i] = new CirclePosition(radius, angle, time);
		float theta = angle / 180 * Mathf.PI;
		Arrye[i].position = new Vector3(circlePosition[i].radius * Mathf.Cos(theta), 
			0f, circlePosition[i].radius * Mathf.Sin(theta));  
	}
	particleSystem.SetParticles(Arrye, Arrye.Length);
}
           

这时候,只要在每次调用update函数时,改变每个粒子的angle,就可以使粒子动起来。 (一个值得注意的问题是,要保证粒子的angle一直保持在360°范围之内)

void Update () {
	int differentiate = 2;
	for (int i = 0; i < count; i++) {
		circlePosition[i].angle -= 0.1f;  
		// 保证angle在0~360度  
		circlePosition[i].angle = (360.0f + circlePosition[i].angle) % 360.0f;
		float theta = circlePosition[i].angle / 180 * Mathf.PI;  
		Arrye[i].position = new Vector3(circlePosition[i].radius * Mathf.Cos(theta), 
			0f, circlePosition[i].radius * Mathf.Sin(theta));
	}
	particleSystem.SetParticles(Arrye, Arrye.Length);
}
           

这时,我们将文件挂载在添加了ParticleSystem组件的空对象上,为了便于观察我设置了两种颜色的粒子系统,分别设置粒子数量和分布范围等:

粒子效果(Lab 9)
粒子效果(Lab 9)
粒子效果(Lab 9)

观察效果:

粒子效果(Lab 9)

可见已经基本完成了实验要求,但现在这些粒子的运动太过死板。

步骤四

解决运动太多死板的问题,我们可以在update中给每一个粒子一个不同的角度增量:

int differentiate = 2;
for (int i = 0; i < count; i++) {
	circlePosition[i].angle -= (i % differentiate + 1) * (speed / circlePosition[i].radius / differentiate); 
           

然后利用PingPong方法,让粒子不是沿着标准的半径移动,而是在一定程度的波动范围内移动: 首先添加共有变量pingPong来规范游离范围:

public float pingPong = 0.01f;  // 游离范围
           

然后在update中更新每个粒子的角度增量:

circlePosition[i].time += Time.deltaTime;  
circlePosition[i].radius += Mathf.PingPong(circlePosition[i].time / minRadius / maxRadius, pingPong) - pingPong / 2.0f;
           

观察结果:

粒子效果(Lab 9)