首先创建粒子系统。

在Hierachy处 右键->Effects->Particle System

默认的Particle System的效果如图(由于Rotation的x值是-90,且粒子具有初速度):

unity控制粒子特效播放的方法有哪些 unity粒子数量在哪里调_Time


将粒子的初速度调为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);
    }
}

unity控制粒子特效播放的方法有哪些 unity粒子数量在哪里调_unity控制粒子特效播放的方法有哪些_02


此时,由于没有Update,粒子系统应该是静态的:

unity控制粒子特效播放的方法有哪些 unity粒子数量在哪里调_Time_03


现在粒子都处于同一半径。我们让粒子分布范围可变,即半径在一个区间内随机取值:

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);
    }
}

这时候就有一点粒子系统的样子了:

unity控制粒子特效播放的方法有哪些 unity粒子数量在哪里调_粒子系统_04


现在,让粒子动起来——根据编号来确定粒子做顺时针运动还是逆时针运动;将粒子分为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);
}

效果如下:

unity控制粒子特效播放的方法有哪些 unity粒子数量在哪里调_i++_05


但是粒子的运动半径太均匀了,缺少一点美感。我们在初始的时候给粒子的半径范围加上一点随机的变化,可以随机的增大或减小:

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);//随机半径,形成环形
...
}

效果如下:

unity控制粒子特效播放的方法有哪些 unity粒子数量在哪里调_i++_06


这样,就完成了一个简单的粒子系统。


改进

1 . 增加闪烁效果

unity控制粒子特效播放的方法有哪些 unity粒子数量在哪里调_粒子系统_07


实现的方法是,每隔固定的时间,选择部分粒子的颜色设置为黑色(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 .增加收束和发散效果

unity控制粒子特效播放的方法有哪些 unity粒子数量在哪里调_i++_08


实现的方法是,用两个数组分别来存储粒子的收敛坐标和发散坐标。用两个信号量来控制收敛和发散,每隔一定时间,对信号量进行赋值,粒子做收束或发散运动。

完整代码如下:

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);
    }
}

如有改进的建议,欢迎您提出!