【Unity 3D遊戲開發學習筆記】粒子光環
阿新 • • 發佈:2019-02-10
實現如下圖的粒子光環:
參考網站: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);
}
}