1. 程式人生 > >【Unity 3D遊戲開發學習筆記】粒子光環

【Unity 3D遊戲開發學習筆記】粒子光環

實現如下圖的粒子光環:
參考網站:http://i-remember.fr/en
思路:
首先宣告定義一個類用於儲存每個粒子的半徑和角度

public class particleClass {
    public float radius = 0.0f; // initialize
    public float angle = 0.0f; // initialize
    public particleClass(float radius_, float angle_)
    {
        radius = radius_;
        angle = angle_;
    }
}

定義宣告一些需要用到的變數,如最大粒子數目,粒子的陣列和儲存粒子半徑和角度類的陣列,內環和外環的半徑,粒子旋轉的速度和分組,分組用於確定粒子順時針或逆時針旋轉。

public int maxParticlesNum = 6000; // the max number of particles
public ParticleSystem particleSystem;
private ParticleSystem.Particle[] particlesArray;
private particleClass[] paticleObject;
public float minRadius = 3.5
f; // inner race radius public float maxRadius = 10.0f; // outer race radius public float speed = 0.23f; // the speed of particles public int group = 2; // group 1 rotates clockwise and group 2 // rotates anticlockwise

Start函式內初始化兩個陣列的大小,並且獲得粒子物件,然後進行遍歷,對每個粒子的位置進行隨機設定,但這裡實際上需要使得粒子儘可能位於環的中心,也就是(maxRaidus+minRadius)/2的位置,下面是直接採用了1個演算法。隨後就儲存每個粒子的位置資訊和設定他的位置。

void Start() {
        particlesArray = new ParticleSystem.Particle[maxParticlesNum];
        paticleObject = new particleClass[maxParticlesNum];
        particleSystem.maxParticles = maxParticlesNum;
        particleSystem.Emit(maxParticlesNum);
        particleSystem.GetParticles(particlesArray);

        for (int i = 0; i < maxParticlesNum; i++) { 
            //random angle produced
            float randomAngle = Random.Range(0.0f, 360.0f);

            // random radius which is closed to the midRadius in a large probility produced
            float midRadius = (maxRadius + minRadius) / 2;
            // quote someone else's algorithm
            float minRate = Random.Range(1.0f, midRadius / minRadius);
            float maxRate = Random.Range(midRadius / maxRadius, 1.0f);
            float randomRadius = Random.Range(minRadius * minRate, maxRadius * maxRate);

            //set two arrays
            // save a new particle's radius & angle
            paticleObject[i] = new particleClass(randomRadius, randomAngle);
            // confirm its position
            particlesArray[i].position = new Vector3(randomRadius * Mathf.Cos(randomAngle), randomRadius * Mathf.Sin(randomAngle), 0.0f);
        }
        //set particle
        particleSystem.SetParticles(particlesArray, maxParticlesNum);
    }

Update函式中,採用奇數和偶數ID來分成兩個組,並且按照i和group來更新他的速度(可以改其他表示式,做到每個粒子速度不會全部相同即可),然後要更新他的角度,因為角度有周期,可能超過360度,採用取餘即可避免這個問題,再次更新粒子位置。

void Update() {
        // run setting, devided in 2 group
        for (int i = 0; i < maxParticlesNum; i++) {
            if (i % 2 == 0) { // judge if this particle should be group 1
                paticleObject[i].angle += (i % group + 1) * speed;
            } else { // or  group 2
                paticleObject[i].angle -= (i % group + 1) * speed;
            }
            //set new position according to the new angle
            paticleObject[i].angle = paticleObject[i].angle % 360;

            float new_angle = paticleObject[i].angle / 180 * Mathf.PI;
            particlesArray[i].position = new Vector3(paticleObject[i].radius * Mathf.Cos(new_angle), paticleObject[i].radius * Mathf.Sin(new_angle), 0f);
        }
        particleSystem.SetParticles(particlesArray, maxParticlesNum);
    }

Inspector設定:
這裡寫圖片描述
執行結果:
這裡寫圖片描述

完整程式碼:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ParRotation : MonoBehaviour {
    public class particleClass {
        public float radius = 0.0f; // initialize
        public float angle = 0.0f; // initialize
        public particleClass(float radius_, float angle_)
        {
            radius = radius_;
            angle = angle_;
        }
    }
    public int maxParticlesNum = 6000; // the max number of particles
    public ParticleSystem particleSystem;
    private ParticleSystem.Particle[] particlesArray;
    private particleClass[] paticleObject;
    public float minRadius = 3.5f; // inner race radius
    public float maxRadius = 10.0f; // outer race radius
    public float speed = 0.23f; // the speed of particles
    public int group = 2; // group 1 rotates clockwise and group 2 rotates anticlockwise

    void Start() {
        particlesArray = new ParticleSystem.Particle[maxParticlesNum];
        paticleObject = new particleClass[maxParticlesNum];
        particleSystem.maxParticles = maxParticlesNum;
        particleSystem.Emit(maxParticlesNum);
        particleSystem.GetParticles(particlesArray);

        for (int i = 0; i < maxParticlesNum; i++) { 
            //random angle produced
            float randomAngle = Random.Range(0.0f, 360.0f);

            // random radius which is closed to the midRadius in a large probility produced
            float midRadius = (maxRadius + minRadius) / 2;
            // quote someone else's algorithm
            float minRate = Random.Range(1.0f, midRadius / minRadius);
            float maxRate = Random.Range(midRadius / maxRadius, 1.0f);
            float randomRadius = Random.Range(minRadius * minRate, maxRadius * maxRate);

            //set two arrays
            // save a new particle's radius & angle
            paticleObject[i] = new particleClass(randomRadius, randomAngle);
            // confirm its position
            particlesArray[i].position = new Vector3(randomRadius * Mathf.Cos(randomAngle), randomRadius * Mathf.Sin(randomAngle), 0.0f);
        }
        //set particle
        particleSystem.SetParticles(particlesArray, maxParticlesNum);
    }

    void Update() {
        // run setting, devided in 2 group
        for (int i = 0; i < maxParticlesNum; i++) {
            if (i % 2 == 0) { // judge if this particle should be group 1
                paticleObject[i].angle += (i % group + 1) * speed;
            } else { // or  group 2
                paticleObject[i].angle -= (i % group + 1) * speed;
            }
            //set new position according to the new angle
            paticleObject[i].angle = paticleObject[i].angle % 360;

            float new_angle = paticleObject[i].angle / 180 * Mathf.PI;
            particlesArray[i].position = new Vector3(paticleObject[i].radius * Mathf.Cos(new_angle), paticleObject[i].radius * Mathf.Sin(new_angle), 0f);
        }
        particleSystem.SetParticles(particlesArray, maxParticlesNum);
    }
}