首先创建粒子系统。
在Hierachy处 右键->Effects->Particle System
默认的Particle System的效果如图(由于Rotation的x值是-90,且粒子具有初速度):
将粒子的初速度调为0,根据自己的需要调整Size和将最大粒子数。例如我将Size调为0.1,Max Particles(最大粒子数)调为10000。再将Emission的Rate over Time调为0,将camera背景调为黑色。
做完这些,新建一个C#脚本来控制粒子系统:
public class MyRing : MonoBehaviour
{
public ParticleSystem particleSystem;
private ParticleSystem.Particle[] particleRing;
public int particleNum = 500;
public float radius = 5.0f;
void Start()
{
particleRing = new ParticleSystem.Particle[particleNum];
particleSystem.maxParticles = particleNum;
particleSystem.Emit(particleNum);
particleSystem.GetParticles(particleRing);
for (int i = 0; i < particleNum; i++)
{
float angle = Random.Range(0.0f, 360.0f);//随机角度
float rad = angle / 180 * Mathf.PI;
particleRing[i].position = new Vector3(radius * Mathf.Cos(angle), radius * Mathf.Sin(angle), 0.0f);
}
particleSystem.SetParticles(particleRing, particleNum);
}
}
此时,由于没有Update,粒子系统应该是静态的:
现在粒子都处于同一半径。我们让粒子分布范围可变,即半径在一个区间内随机取值:
public class MyRing : MonoBehaviour
{
public ParticleSystem particleSystem;
private ParticleSystem.Particle[] particleRing;
public int particleNum = 500;
public float radius = 5.0f;
public float minRadius = 3.0f;
void Start()
{
particleRing = new ParticleSystem.Particle[particleNum];
particleSystem.maxParticles = particleNum;
particleSystem.Emit(particleNum);
particleSystem.GetParticles(particleRing);
for (int i = 0; i < particleNum; i++)
{
float angle = Random.Range(0.0f, 360.0f);//随机角度
float r = Random.Range(minRadius, radius);//随机半径,形成环形
float rad = angle / 180 * Mathf.PI;
particleRing[i].position = new Vector3(r * Mathf.Cos(angle), r * Mathf.Sin(angle), 0.0f);
}
particleSystem.SetParticles(particleRing, particleNum);
}
}
这时候就有一点粒子系统的样子了:
现在,让粒子动起来——根据编号来确定粒子做顺时针运动还是逆时针运动;将粒子分为10个层,设置粒子数量为2000。最外层的速度最快:
public int level = 10;
...
void Update()
{
for(int i = 0; i < particleNum; i++)
{
if (i%2 == 0)
{
particleAngle[i] += (i % level + 1) * speed;//逆时针
particleAngle[i] %= 360;
}
else
{
particleAngle[i] -= (i % level + 1) * speed;//顺时针
if (particleAngle[i] < 0) particleAngle[i] += 360;
}
// Debug.Log(particleAngle[i]);
float rad = particleAngle[i] / 180 * Mathf.PI;
particleRing[i].position = new Vector3(particleRadius[i] * Mathf.Cos(rad),
particleRadius[i] * Mathf.Sin(rad), 0.0f);
}
particleSystem.SetParticles(particleRing, particleNum);
}
效果如下:
但是粒子的运动半径太均匀了,缺少一点美感。我们在初始的时候给粒子的半径范围加上一点随机的变化,可以随机的增大或减小:
void Start(){
...
float tempMin = Random.Range(minRadius * 0.8f, minRadius * 1.2f);
float tempMax = Random.Range(radius * 0.8f, radius * 1.2f);
particleRadius[i] = Random.Range(tempMin, tempMax);//随机半径,形成环形
...
}
效果如下:
这样,就完成了一个简单的粒子系统。
改进
1 . 增加闪烁效果
实现的方法是,每隔固定的时间,选择部分粒子的颜色设置为黑色(0,0,0),或将黑色恢复为白色(255,255,255):
public int count = 0;
...
void Update(){
count++;
...
if (count % 100 == 0)
{
if (i % 3 == 0 || i % 5 == 0)
{
if (particleRing[i].color.r == 0)
{
particleRing[i].color = new Color(255, 255, 255);
}
else particleRing[i].color = new Color(0, 0, 0);
}
}
...
}
2 .增加收束和发散效果
实现的方法是,用两个数组分别来存储粒子的收敛坐标和发散坐标。用两个信号量来控制收敛和发散,每隔一定时间,对信号量进行赋值,粒子做收束或发散运动。
完整代码如下:
public class MyRing : MonoBehaviour
{
public ParticleSystem particleSystem;
private ParticleSystem.Particle[] particleRing;
private float[] particleAngle;//粒子偏转角
private float[] particleRadius;//粒子半径
private float[] convergent;//收束半径
private float[] divergent;//发散半径
public int particleNum = 2000;
public float radius = 5.0f;
public float minRadius = 3.0f;
public float speed = 0.1f;
public int level = 10;
public int count = 0;
public bool conFlag = false;//控制收束
public bool divFlag = false;//控制发散
public float convergentSpeed = 3.0f;
void Start()
{
particleRing = new ParticleSystem.Particle[particleNum];
particleAngle = new float[particleNum];
particleRadius = new float[particleNum];
convergent = new float[particleNum];
divergent = new float[particleNum];
particleSystem.maxParticles = particleNum;
particleSystem.Emit(particleNum);
particleSystem.GetParticles(particleRing);
for (int i = 0; i < particleNum; i++)
{
particleAngle[i] = Random.Range(0.0f, 360.0f);//随机角度
float tempMin = Random.Range(minRadius * 0.8f, minRadius * 1.2f);
float tempMax = Random.Range(radius * 0.8f, radius * 1.2f);
particleRadius[i] = Random.Range(tempMin, tempMax);//随机半径,形成环形.
convergent[i] = particleRadius[i]*0.6f;
divergent[i] = particleRadius[i];
float rad = particleAngle[i] / 180 * Mathf.PI;
particleRing[i].position = new Vector3(particleRadius[i] * Mathf.Cos(rad),
particleRadius[i] * Mathf.Sin(rad), 0.0f);
}
particleSystem.SetParticles(particleRing, particleNum);
}
void Update()
{
count++;
if (count % 100 == 0)
{
//收束或发散
if (conFlag)
{
conFlag = false;
divFlag = true;
}
else
{
conFlag = true;
divFlag = false;
}
}
for (int i = 0; i < particleNum; i++)
{
if (i % 2 == 0)
{
particleAngle[i] += (i % level + 1) * speed;//逆时针
particleAngle[i] %= 360;
}
else
{
particleAngle[i] -= (i % level + 1) * speed;//顺时针
if (particleAngle[i] < 0) particleAngle[i] += 360;
}
if (conFlag)//收束
{
if(particleRadius[i]>convergent[i])
particleRadius[i] -= convergentSpeed * (particleRadius[i] / convergent[i]) * Time.deltaTime;
}
if(divFlag)//发散
{
if (particleRadius[i] < divergent[i])
{
particleRadius[i] += convergentSpeed * (divergent[i] / particleRadius[i]) * Time.deltaTime;
}
}
float rad = particleAngle[i] / 180 * Mathf.PI;
particleRing[i].position = new Vector3(particleRadius[i] * Mathf.Cos(rad),
particleRadius[i] * Mathf.Sin(rad), 0.0f);
}
particleSystem.SetParticles(particleRing, particleNum);
}
}
如有改进的建议,欢迎您提出!