粒子光環製作
參考 http://i-remember.fr/en 這類網站,使用粒子流編程控制製作一些效果, 如“粒子光環”
在本次作業中,我使用粒子系統製作了一個彩虹效果的煙花。
基本步驟
首先,新建一個空對象Halo,並添加子對象,然後加入粒子系統:
然後新建腳本Halo,在腳本中完成具體粒子效果的實現。
private ParticleSystem particleSys; // 粒子系統
private ParticleSystem.Particle[] particleArr; // 粒子數組
private ParticleInfo[] particles; // 粒子位置數組
public Gradient colorGradient; // 粒子顏色改變器
public int count = 10000; // 粒子數量
public float size = 0.03f; // 粒子大小
public float minRadius = 5.0f; // 最小半徑
public float maxRadius = 12.0f; // 最大半徑
public bool clockwise = true; // 順時針|逆時針
public float speed = 2f; // 速度
public float pingPong = 0.02f; // 遊離範圍
首先在Halo中聲明需要用到的相關變量,包括了粒子系統、數組、位置數組以及粒子的數量、大小和半徑範圍等參數。
public class ParticleInfo
{
public float radius = 0f, angle = 0f, time = 0f;
public ParticleInfo(float x, float y, float z)
{
radius = x;
angle = y;
time = z;
}
}
ParticleInfo類定義了每個粒子的半徑、角度和時間,方便之後的處理。
void RandomlySpread()
{
for (int i = 0; i < count; i ++)
{
// 隨機粒子距離中心的半徑
float midR = (maxRadius + minRadius) / 2;
float minRate = Random.Range(1, midR / minRadius);
float maxRate = Random.Range(midR / maxRadius, 1);
float R = Random.Range(minRadius * minRate, maxRadius * maxRate);
// 隨機每個粒子的角度
float angle = Random.Range(0, 360);
float theta = angle / 180 * Mathf.PI;
// 隨機每個粒子的遊離起始時間
float time = Random.Range(0.0f, 360.0f);
particles[i] = new ParticleInfo(R, angle, time);
particleArr[i].position = new Vector3(particles[i].radius * Mathf.Cos(theta), 0f, particles[i].radius * Mathf.Sin(theta));
}
particleSys.SetParticles(particleArr, particleArr.Length);
}
RandomlySpread函數用來賦予每個粒子一個初始的位置,在一定範圍內隨機生成每個粒子的位置、角度遊離時間。我們希望粒子總體集中在平均半徑附近,這樣看起來比較美觀。
// Start is called before the first frame update
void Start()
{
//initialize
particleArr = new ParticleSystem.Particle[count];
particles = new ParticleInfo[count];
// 初始化粒子系統
particleSys = this.GetComponent<ParticleSystem>();
particleSys.startSpeed = 0; // 粒子位置由程序控制
particleSys.startSize = size; // 設置粒子大小
particleSys.loop = false;
particleSys.maxParticles = count; // 設置最大粒子量
particleSys.Emit(count); // 發射粒子
particleSys.GetParticles(particleArr);
RandomlySpread(); // 初始化各粒子位置
}
Start中初始化粒子數組和粒子系統,並初始化粒子的位置(調用RandomlySpread函數)。
void Update()
{
for (int i = 0; i < count; i++)
{
if (clockwise)
particles[i].angle -= (i % tier + 1) * (speed / particles[i].radius / tier);
else
particles[i].angle += (i % tier + 1) * (speed / particles[i].radius / tier);
particles[i].angle = (360.0f + particles[i].angle) % 360.0f;
float theta = particles[i].angle / 180 * Mathf.PI;
float x = 10 * Mathf.Sin(8 * theta) * Mathf.Cos(theta);
float y = 10 * Mathf.Sin(8 * theta) * Mathf.Sin(theta);
particleArr[i].position = new Vector3(x, 0f, y + Random.Range(-1f, 1f));
// 粒子在半徑方向上游離
particles[i].time += Time.deltaTime;
particles[i].radius += Mathf.PingPong(particles[i].time / minRadius / maxRadius, pingPong) - pingPong / 2.0f;
//改變粒子透明度
particleArr[i].color = colorGradient.Evaluate(Random.value);
}
particleSys.SetParticles(particleArr, particleArr.Length);
}
Update函數用來更新粒子的位置,首先通過設置一個差分層變量tier將粒子系統分爲十層,每一層角度的增量都不相同,這就使得粒子系統的運動更加美觀。clockwise決定旋轉的方向。由於總體是圓形,所以要保證粒子的角度在0-360度之間。此外,還有一個PingPong函數,使得粒子在一個半徑範圍內來回地波動。
爲了使粒子系統呈現煙花的形狀。我在這裏使用了玫瑰線函數,該函數圖像及參數方程如下:
r = 10
x = rsin(10t)cos(t)
y = rsin(10*t)*sin(t)
可以通過調整數值來改變葉片的數量。
通過將粒子數組的position設置爲該函數來使得粒子系統呈現煙花狀:
float theta = particles[i].angle / 180 * Mathf.PI;
float x = 10 * Mathf.Sin(8 * theta) * Mathf.Cos(theta);
float y = 10 * Mathf.Sin(8 * theta) * Mathf.Sin(theta);
particleArr[i].position = new Vector3(x, 0f, y + Random.Range(-1f, 1f));
最後,創建三個粒子系統,並分別加上紅黃藍三種顏色,將它們疊加在一起,最後就可以看到一個彩虹色的煙花了: