做个简单的粒子效果

简介

这次打算用Unity实现一个如这个网站的粒子效果。(注意:只是粒子效果,不是所有的效果。。)Unity的粒子效果十分的强大,不仅仅能做出粒子海洋这样的东西,而且还能实现爆炸等特效。这篇博客参考了这个教程,这篇教程简单易入手,用来入门粒子效果十分的好,推荐大家去看一下。

实现

那个网站中有两种粒子效果,所以,我们打算分开来处理两种粒子。先是背景的橙黄粒子。我们发现,该粒子的效果跟我推荐的那个教程的粒子海洋的效果相同,所以,这里我也不打算讲解太多,顺便说一声,柏林噪声实在是太神奇了。粒子参数设定如下:
做个简单的粒子效果_第1张图片
做个简单的粒子效果_第2张图片
代码如下(与推荐教程的代码相同,只是改了改速度而已):
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; ifor(int j = 0; 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,然后颜色设为黑色就行。
做个简单的粒子效果_第3张图片
效果如下:
做个简单的粒子效果_第4张图片
虽然。。颜色有点不大对。。但至少效果做出来了嘛。。
然后我们再制作下一个粒子特效,下一个粒子特效是,先是一个粒子圆环在运动,然后当鼠标移到圆环里面的时候,圆环粒子就立即变得集中起来,我的实现方法是,当鼠标在圆环外时,圆环的宽度会大一点,然后当鼠标移到圆环内部时,圆环的宽度就会缩小。代码如下:
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;i4.5f + Random.Range (-0.2f, 0.2f);
            turn = false;
        }
        if (distance > 4.0f && !turn) {
            for (int i=0;i4.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),代码的其他部分我觉得不需要怎么解释了,就是通过简单的三角函数,将极坐标转换成直角座标而已。效果如下:
做个简单的粒子效果_第5张图片
嗯。。效果。。差。。不多吧。。就做到这吧。。

总结

其实感觉用Unity处理粒子并不是非常的难,一般的流程就是,在Start()里面生成粒子,然后在Update()里面更新粒子的位置,然后就能获得一个粒子效果了,虽然。。我做的跟目标还差一点。。但我觉得,还挺好的啦(强行挺好)。最后来个两个粒子的合照吧。
做个简单的粒子效果_第6张图片
还挺不错的对吧。。(捂脸)

你可能感兴趣的:(3D游戏设计,unity)