Particle System

Learning the game of 3D particle systems, refer to the I-remember examples of the halo on, decide to do a. Before starting the hands, and require careful observation found, halo two layers, one layer further clockwise rotated counterclockwise, the intermediate portion and the large particles; between the particles will be free to rotate at the same halo.

Base ready

New empty object ParticleCircle, to build two sub-objects Clockwise and Anticlockwise, to add a Particle System components, the new ParticleCircle script and mount on child objects:

      
      
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
      
      
using UnityEngine;
using System.Collections;
public class CirclePosition
{
public float radius = 0f, angle = 0f, time = 0f;
public (float radius, float angle, float time)
{
this.radius = radius;
this.angle = angle;
this.time = time;
}
}
public class ParticleCircle : MonoBehaviour {
private ParticleSystem particleSys; // 粒子系统
private ParticleSystem.Particle[] particleArr;
private CirclePosition[] circle; // 极坐标数组
public int count = 10000; // 粒子数量
public float size = 3f; // 粒子大小
public float minRadius = 4.0f; // 最小半径
public float maxRadius = 8.0f; // 最大半径
public bool clockwise = true; // 顺时针|逆时针
public float speed = 2f; // 速度
public float pingPong = 0.02f; // 游离范围
private int tier = 10; // 速度差分层数
public Gradient colorGradient; // 颜色控制
void RandomlySpread() // 随机布置粒子位置
{
for ( int i = 0; i < count; ++i)
{
float midRadius = (maxRadius + minRadius)/ 2;
float minRate = Random.Range( 1.0f, midRadius/minRadius);
float maxRate = Random.Range(midRadius/maxRadius, 1.0f);
float radius = Random.Range(minRadius * minRate, maxRadius * maxRate);
float angle = Random.Range( 0.0f, 360.0f); // 随机每个粒子的角度
float theta = angle/ 180 * Mathf.PI;
float time = Random.Range( 0.0f, 360.0f); // 随机每个粒子的游离起始时间
circle[i] = new CirclePosition(radius, angle, time);
particleArr[i].position = new Vector3(circle[i].radius * Mathf.Cos(theta), 0f, circle[i].radius * Mathf.Sin(theta));
}
particleSys.SetParticles(particleArr, particleArr.Length);
}
void Start () {
particleArr = new ParticleSystem.Particle[count]; // 初始化粒子数组
circle = new CirclePosition[count];
particleSys = this.GetComponent<ParticleSystem>(); // 初始化粒子系统
particleSys.startSpeed = 0;
particleSys.startSize = size;
particleSys.loop = false;
particleSys.maxParticles = count; // 设置最大粒子量
particleSys.Emit(count); // 发射粒子
particleSys.GetParticles(particleArr);
RandomlySpread(); // 初始化各粒子位置
}

旋转粒子

在Update函数里逐渐改变粒子的角度使粒子旋转,其中tier使粒子角度改变量不一致,这样粒子旋转就不会看起来像是图片在旋转:

      
      
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
      
      
void Update () { // 通过改变角度使粒子旋转
for ( int i = 0; i < count; i++)
{
if (clockwise)
circle[i].angle -= (i%tier + 1)*(speed/circle[i].radius/tier);
else
circle[i].angle += (i%tier + 1)*(speed/circle[i].radius/tier);
circle[i].angle = ( 360.0f + circle[i].angle)% 360.0f; // 保证angle在0~360度
float theta = circle[i].angle/ 180 * Mathf.PI;
particleArr[i].position = new Vector3(circle[i].radius * Mathf.Cos(theta), 0f, circle[i].radius * Mathf.Sin(theta));
}
particleSys.SetParticles(particleArr, particleArr.Length);
}

游离粒子

Unity的Mathf的PingPong函数使得值在范围内来回变动,使用它让粒子半径来回变动。以下添加到Update函数中:

      
      
1
2
      
      
circle[i].time += Time.deltaTime;
circle[i].radius += Mathf.PingPong(circle[i].time / minRadius / maxRadius, pingPong) - pingPong / 2.0f;

添加透明度

仔细观察i-remember会发现不同地方亮度不同,也可以说是透明度不同,使用Gradient类可以解决这个问题。一下添加到start函数中:

      
      
1
2
3
4
5
6
7
8
9
10
      
      
GradientAlphaKey[] alphaKeys = new GradientAlphaKey[ 5]; // 初始化梯度颜色控制器
alphaKeys[ 0].time = 0.0f; alphaKeys[ 0].alpha = 1.0f;
alphaKeys[ 1].time = 0.4f; alphaKeys[ 1].alpha = 0.4f;
alphaKeys[ 2].time = 0.6f; alphaKeys[ 2].alpha = 1.0f;
alphaKeys[ 3].time = 0.9f; alphaKeys[ 3].alpha = 0.4f;
alphaKeys[ 4].time = 1.0f; alphaKeys[ 4].alpha = 0.9f;
GradientColorKey[] colorKeys = new GradientColorKey[ 2];
colorKeys[ 0].time = 0.0f; colorKeys[ 0].color = Color.white;
colorKeys[ 1].time = 1.0f; colorKeys[ 1].color = Color.white;
大专栏   粒子系统 class="line">colorGradient.SetKeys(colorKeys, alphaKeys);

然后在Update中根据粒子的角度改变粒子的透明度:

      
      
1
      
      
particleArr[i].color = colorGradient.Evaluate(circle[i].angle / 360.0f);

修改参数

修改主摄像机到合适位置:

另外一层是逆时针旋转的,因此把clockwise的勾去掉,同时修改参数直到效果满意:

完整代码

      
      
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
      
      
using UnityEngine;
using System.Collections;
public class CirclePosition
{
public float radius = 0f, angle = 0f, time = 0f;
public (float radius, float angle, float time)
{
this.radius = radius;
this.angle = angle;
this.time = time;
}
}
public class ParticleCircle : MonoBehaviour {
private ParticleSystem particleSys; // 粒子系统
private ParticleSystem.Particle[] particleArr;
private CirclePosition[] circle; // 极坐标数组
public int count = 10000; // 粒子数量
public float size = 3f; // 粒子大小
public float minRadius = 4.0f; // 最小半径
public float maxRadius = 8.0f; // 最大半径
public bool clockwise = true; // 顺时针|逆时针
public float speed = 2f; // 速度
public float pingPong = 0.02f; // 游离范围
private int tier = 10; // 速度差分层数
public Gradient colorGradient; // 颜色控制
void RandomlySpread() // 随机布置粒子位置
{
for ( int i = 0; i < count; ++i)
{
float midRadius = (maxRadius + minRadius)/ 2;
float minRate = Random.Range( 1.0f, midRadius/minRadius);
float maxRate = Random.Range(midRadius/maxRadius, 1.0f);
float radius = Random.Range(minRadius * minRate, maxRadius * maxRate);
float angle = Random.Range( 0.0f, 360.0f); // 随机每个粒子的角度
float theta = angle/ 180 * Mathf.PI;
float time = Random.Range( 0.0f, 360.0f); // 随机每个粒子的游离起始时间
circle[i] = new CirclePosition(radius, angle, time);
particleArr[i].position = new Vector3(circle[i].radius * Mathf.Cos(theta), 0f, circle[i].radius * Mathf.Sin(theta));
}
particleSys.SetParticles(particleArr, particleArr.Length);
}
void Start () {
particleArr = new ParticleSystem.Particle[count]; // 初始化粒子数组
circle = new CirclePosition[count];
particleSys = this.GetComponent<ParticleSystem>(); // 初始化粒子系统
particleSys.startSpeed = 0;
particleSys.startSize = size;
particleSys.loop = false;
particleSys.maxParticles = count; // 设置最大粒子量
particleSys.Emit(count); // 发射粒子
particleSys.GetParticles(particleArr);
RandomlySpread(); // 初始化各粒子位置
GradientAlphaKey[] alphaKeys = new GradientAlphaKey[ 5]; // 初始化梯度颜色控制器
alphaKeys[ 0].time = 0.0f; alphaKeys[ 0].alpha = 1.0f;
alphaKeys[ 1].time = 0.4f; alphaKeys[ 1].alpha = 0.4f;
alphaKeys[ 2].time = 0.6f; alphaKeys[ 2].alpha = 1.0f;
alphaKeys[ 3].time = 0.9f; alphaKeys[ 3].alpha = 0.4f;
alphaKeys[ 4].time = 1.0f; alphaKeys[ 4].alpha = 0.9f;
GradientColorKey[] colorKeys = new GradientColorKey[ 2];
colorKeys[ 0].time = 0.0f; colorKeys[ 0].color = Color.white;
colorKeys[ 1].time = 1.0f; colorKeys[ 1].color = Color.white;
colorGradient.SetKeys(colorKeys, alphaKeys);
}
void Update () { // 通过改变角度使粒子旋转
for ( int i = 0; i < count; i++)
{
if (clockwise)
circle[i].angle -= (i%tier + 1)*(speed/circle[i].radius/tier);
else
circle[i].angle += (i%tier + 1)*(speed/circle[i].radius/tier);
circle[i].angle = ( 360.0f + circle[i].angle)% 360.0f; // 保证angle在0~360度
float theta = circle[i].angle/ 180 * Mathf.PI;
particleArr[i].position = new Vector3(circle[i].radius * Mathf.Cos(theta), 0f, circle[i].radius * Mathf.Sin(theta));
circle[i].time += Time.deltaTime; // 使粒子半径波动
circle[i].radius += Mathf.PingPong(circle[i].time/minRadius/maxRadius, pingPong) - pingPong/ 2.0f;
particleArr [I] = colorGradient.Evaluate .color (Circle [I] .angle / 360.0f ); // change the transparency in accordance with the angle
}
particleSys.SetParticles(particleArr, particleArr.Length);
}
}

ParticleSea

The following is another particle system written in particle oceans are interested can do some:

Guess you like

Origin www.cnblogs.com/lijianming180/p/12433283.html