这次要使用unity3d仿制这个网站上的光环的效果:
1.要使用粒子系统,第一步就是创建一个粒子系统。
2.粒子移动的轨迹,我们使用数学方法实现,在update中每帧更新粒子的位置。因此将粒子的初速度设为0,并把emission Rate设为0,因为希望粒子有不同的大小,因此设置粒子的初始大小在一个范围内随机产生。
3.我们只需要确定半径,就可以将粒子放置在圆的轨道上,随机产生一个角度就可以将粒子随机放置在轨道上
4.新建C#脚本,并获取粒子系统,设置发射数目,新建例子,设置初始位置,给粒子系统设置粒子
public ParticleSystem particleSystem;
private ParticleSystem.Particle[] particleRing;
public int particleNum = 200;
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);
}
效果如图:
5.将粒子从圆轨道扩展为圆环轨道
public ParticleSystem particleSystem;
private ParticleSystem.Particle[] particleRing;
public int particleNum = 200;
public float radius = 5.0f;
public float maxRadius = 8.0f;
// Use this for initialization
void Start () {
particleRing = new ParticleSystem.Particle[particleNum];
particleSystem.maxParticles = particleNum;
particleSystem.Emit(particleNum);
particleSystem.GetParticles(particleRing);
for (int i = 0; i < particleNum; i++) {
float r = Random.Range(radius, maxRadius);
float angle = Random.Range(0.0f, 360.0f);
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);
}
效果如下:
6.让粒子运动起来(仔细观察网站的运动效果,其实是很多部分的粒子,每一部分的粒子的运动是一致的,旋转的角度,顺时针还是逆时针):
//在初始化的时候记录下粒子的半径和角度
particleAngle[i] = angle;
particleR[i] = r;
//update
void Update () {
//设置为5部分的粒子,能被2整除的部分逆时针旋转,否则顺时针
for(int i = 0;i < particleNum; i++) {
if(i%2 == 0) {
particleAngle[i] += (i % level+1) * speed;
} else {
particleAngle[i] -= (i % level+1) * speed;
}
particleAngle[i] = particleAngle[i] % 360;
float rad = particleAngle[i] / 180 * Mathf.PI;
particleRing[i].position = new Vector3(particleR[i] * Mathf.Cos(rad), particleR[i] * Mathf.Sin(rad), 0f);
}
particleSystem.SetParticles(particleRing, particleNum);
}
效果如图:
7.现在的问题在于粒子的分布非常平均,仔细观察网站上的光环,效果是在圆环中部的粒子更多,在内圈和外圈的是游离的粒子。所以,我们要做的是将内外的部分粒子分布在中心,我们更改一下半径的随机函数。
float midR = (maxRadius + radius)/2;
//最小半径随机扩大
float rate1 = Random.Range(1.0f, midR / radius);
//最大半径随机缩小
float rate2 = Random.Range(midR / maxRadius, 1.0f);
float r = Random.Range(radius*rate1, maxRadius*rate2);
效果如图:
8.将粒子大小调为0.05-0.15,粒子数调为10000,最大半径调为10.0
9.收缩效果:实现思路:记录收缩后的位置和收缩前的位置,在每一个update里根据按下的按钮调节每一个粒子的半径。
//收缩前和后位置的初始化
particleR[i] = r;
circleR[i] = r;
collectR[i] = r - 1.5f * (r / radius);
if (collectR[i] < radius+0.5f) {
float midRadius = radius + 0.25f;
float minRate = Random.Range(1.0f, midRadius / radius);
collectR[i] = Random.Range(radius*minRate, (radius + 0.5f));
}
//触发函数
public void Collect() {
collect = true;
}
public void outCollect() {
collect = false;
}
在update的循环里加入判断
void Update () {
for(int i = 0;i < particleNum; i++) {
if (collect == true) {
if (particleR[i] > collectR[i]) {
particleR[i] -= collectSpeed *(particleR[i]/collectR[i]) * Time.deltaTime;
}
} else {
if (particleR[i] < circleR[i]) {
particleR[i] += collectSpeed * (circleR[i] / particleR[i]) * Time.deltaTime;
}else if(particleR[i] > circleR[i]) {
particleR[i] = circleR[i];
}
}
}
最终效果:
//Particle_ring.cs
using UnityEngine;
using System.Collections;
public class Particle_ring : MonoBehaviour {
public ParticleSystem particleSystem;
private ParticleSystem.Particle[] particleRing;
public int particleNum = 10000;
public float radius = 5.0f;
public float maxRadius = 10.0f;
public int level = 5;
private float[] particleAngle;
private float[] particleR;
private float[] collectR;
private float[] circleR;
float collectSpeed = 2.0f;
private bool collect = false;
public float speed = 0.1f;
void Start () {
particleRing = new ParticleSystem.Particle[particleNum];
particleAngle = new float[particleNum];
particleR = new float[particleNum];
collectR = new float[particleNum];
circleR = new float[particleNum];
particleSystem.maxParticles = particleNum;
particleSystem.Emit(particleNum);
particleSystem.GetParticles(particleRing);
for (int i = 0; i < particleNum; i++) {
float midR = (maxRadius + radius)/2;
//最小半径随机扩大
float rate1 = Random.Range(1.0f, midR / radius);
//最大半径随机缩小
float rate2 = Random.Range(midR / maxRadius, 1.0f);
float r = Random.Range(radius*rate1, maxRadius*rate2);
float angle = Random.Range(0.0f, 360.0f);
particleAngle[i] = angle;
particleR[i] = r;
circleR[i] = r;
collectR[i] = r - 1.5f * (r / radius);
if (collectR[i] < radius+0.5f) {
float midRadius = radius + 0.25f;
float minRate = Random.Range(1.0f, midRadius / radius);
collectR[i] = Random.Range(radius*minRate, (radius + 0.5f));
}
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);
}
void Update () {
//设置为5部分的粒子,能被2整除的部分逆时针旋转,否则顺时针
for(int i = 0;i < particleNum; i++) {
if (collect == true) {
if (particleR[i] > collectR[i]) {
particleR[i] -= collectSpeed *(particleR[i]/collectR[i]) * Time.deltaTime;
}
} else {
if (particleR[i] < circleR[i]) {
particleR[i] += collectSpeed * (circleR[i] / particleR[i]) * Time.deltaTime;
}else if(particleR[i] > circleR[i]) {
particleR[i] = circleR[i];
}
}
if (i%2 == 0) {
particleAngle[i] += (i % level+1) * speed;
} else {
particleAngle[i] -= (i % level+1) * speed;
}
particleAngle[i] = particleAngle[i] % 360;
float rad = particleAngle[i] / 180 * Mathf.PI;
particleRing[i].position = new Vector3(particleR[i] * Mathf.Cos(rad), particleR[i] * Mathf.Sin(rad), 0f);
}
particleSystem.SetParticles(particleRing, particleNum);
}
public void Collect() {
collect = true;
}
public void outCollect() {
collect = false;
}
}
1
FIN 5.2/23.50