做个简单的粒子效果
简介
这次打算用Unity实现一个如这个网站的粒子效果。(注意:只是粒子效果,不是所有的效果。。)Unity的粒子效果十分的强大,不仅仅能做出粒子海洋这样的东西,而且还能实现爆炸等特效。这篇博客参考了这个教程,这篇教程简单易入手,用来入门粒子效果十分的好,推荐大家去看一下。
实现
那个网站中有两种粒子效果,所以,我们打算分开来处理两种粒子。先是背景的橙黄粒子。我们发现,该粒子的效果跟我推荐的那个教程的粒子海洋的效果相同,所以,这里我也不打算讲解太多,顺便说一声,柏林噪声实在是太神奇了。粒子参数设定如下:
代码如下(与推荐教程的代码相同,只是改了改速度而已):
ParticleSea.cs
using UnityEngine;
using System.Collections;
public class ParticleSea : MonoBehaviour {
public ParticleSystem particleSystem;
private ParticleSystem.Particle[] particlesArray;
public int seaResolution;
public float spacing;
public float noiseScale;
public float heightScale;
private float perlinNoiseAnimX = 0.01f;
private float perlinNoiseAnimY = 0.01f;
public Gradient colorGradient;
void Start() {
particlesArray = new ParticleSystem.Particle[seaResolution * seaResolution];
particleSystem.maxParticles = seaResolution * seaResolution;
particleSystem.Emit(seaResolution * seaResolution);//Emit the particle
particleSystem.GetParticles(particlesArray);
}
void Update() {
for(int i = 0; i<seaResolution; i++) {
for(int j = 0; j <seaResolution; j++) {
float zPos = Mathf.PerlinNoise(i * noiseScale + perlinNoiseAnimX, j * noiseScale + perlinNoiseAnimY);
particlesArray[i * seaResolution + j].color = colorGradient.Evaluate(zPos);
particlesArray[i * seaResolution + j].position = new Vector3(i * spacing, zPos * heightScale, j * spacing);
}
}
perlinNoiseAnimX += 0.001f;//Control the Particles' rate
perlinNoiseAnimY += 0.001f;
particleSystem.SetParticles(particlesArray, particlesArray.Length);
}
}
原理其实很简单,其实就是先在Start()函数中生成并释放一批粒子,然后再在每一帧的时候改变它们的位置,使它们显现出一种连续的移动的效果。在运行之前,需要将摄像机的背景设为黑色,选中主摄像机的Clear Flag改为Solid Color,然后颜色设为黑色就行。
效果如下:
虽然。。颜色有点不大对。。但至少效果做出来了嘛。。
然后我们再制作下一个粒子特效,下一个粒子特效是,先是一个粒子圆环在运动,然后当鼠标移到圆环里面的时候,圆环粒子就立即变得集中起来,我的实现方法是,当鼠标在圆环外时,圆环的宽度会大一点,然后当鼠标移到圆环内部时,圆环的宽度就会缩小。代码如下:
ParticleCircle.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ParticleCircle : MonoBehaviour {
public ParticleSystem particleSystem;
public GameObject gameobject;
private ParticleSystem.Particle[] particlesArray;
private float[] rad_particle;//To store each particle position
private float[] r_particle;//To store each particle radius
private float radius=10.0f;
private bool turn = true;
public int num_particle;
// Use this for initialization
void Start () {
particlesArray = new ParticleSystem.Particle[num_particle];
rad_particle = new float[num_particle];
r_particle = new float[num_particle];
particleSystem.maxParticles = num_particle;
particleSystem.Emit(num_particle);
particleSystem.GetParticles(particlesArray);
for (int i = 0; i < num_particle; i++) {
rad_particle [i] = Random.Range (0.0f, 2 * Mathf.PI);
r_particle[i] = 4.5f+Random.Range (-0.5f, 0.5f);
particlesArray [i].position = new Vector3 (r_particle[i] * Mathf.Cos (rad_particle [i]), r_particle[i] * Mathf.Sin (rad_particle [i]), 0.0f);
}
particleSystem.SetParticles(particlesArray, particlesArray.Length);
}
// Update is called once per frame
void Update () {
Vector3 mp = Input.mousePosition;
Vector3 pos = gameobject.transform.position;
Vector3 tp = Camera.main.ScreenToWorldPoint (new Vector3 (mp.x, mp.y, 10.0f));
float distance = Mathf.Sqrt ((tp.x - pos.x) * (tp.x - pos.x) + (tp.y - pos.y) * (tp.y - pos.y));
if (distance < 4.0f && turn) {
for (int i=0;i<num_particle;i++) r_particle [i] = 4.5f + Random.Range (-0.2f, 0.2f);
turn = false;
}
if (distance > 4.0f && !turn) {
for (int i=0;i<num_particle;i++) r_particle[i] = 4.5f+Random.Range (-0.5f, 0.5f);
turn = true;
}
for (int i = 0; i < num_particle; i++) {
rad_particle [i] += Random.Range (0.0f, 0.005f);
particlesArray [i].position = new Vector3 (r_particle[i] * Mathf.Cos (rad_particle [i]), r_particle[i] * Mathf.Sin (rad_particle [i]), 0.0f);
}
particleSystem.SetParticles(particlesArray, particlesArray.Length);
}
}
这里需要提一点的是,我们怎么判断鼠标移到圆环里了呢?我用的方法是,获取鼠标的位置,然后计算鼠标与圆环中心的距离,当距离小于内径的时候,就表示在圆环里面了,有趣的是,当我去搜索如何获得鼠标位置的时候,发现一个问题,官方提供的获取鼠标位置的Input.mousePosition返回的是鼠标在桌面上的绝对位置,而不是在游戏界面的位置,于是我继续的百度,发现了可以通过摄像机的投射范围来获得鼠标在游戏中的位置,代码如下:
Camera.main.ScreenToWorldPoint (Input.mousePosition);
需要注意的是,一般来说摄像机为了能拍到游戏界面,z设置一般为负值,这个时候,你需要在鼠标的绝对位置上加入摄像机z值的绝对值,就像我上面的代码一样,那个10.0f是因为摄像机的位置在(0,0,-10),代码的其他部分我觉得不需要怎么解释了,就是通过简单的三角函数,将极坐标转换成直角座标而已。效果如下:
嗯。。效果。。差。。不多吧。。就做到这吧。。
总结
其实感觉用Unity处理粒子并不是非常的难,一般的流程就是,在Start()里面生成粒子,然后在Update()里面更新粒子的位置,然后就能获得一个粒子效果了,虽然。。我做的跟目标还差一点。。但我觉得,还挺好的啦(强行挺好)。最后来个两个粒子的合照吧。
还挺不错的对吧。。(捂脸)
上一篇: 链表练习 两数相加 python
下一篇: 内存重叠问题