Unity3d学习之路——粒子光环

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ke1950523491/article/details/80496843

Unity3d学习之路——粒子光环

作业要求:

本次作业基本要求是三选一

  • 1.简单粒子制作
    按参考资源要求,制作一个粒子系统,参考资源
    使用 3.3 节介绍,用代码控制使之在不同场景下效果不一样
  • 2.完善官方的“汽车尾气”模拟
    使用官方资源资源 Vehicle 的 car, 使用 Smoke 粒子系统模拟启动发动、运行、故障等场景效果
  • 3.参考 http://i-remember.fr/en 这类网站,使用粒子流编程控制制作一些效果, 如“粒子光环”

对粒子光环效果很迷恋,所以选了第三个,这个要做得好真的难,还好有往年的博客参考,相关资料链接在文章末尾:先看一下成品图:

这里写图片描述

录屏的效果还是有点差

实现过程:

  • Step1:先定义一个类用来记录每个粒子的属性:
public class ParticleData
{
    public float radius, angle, time;
    public ParticleData(float radius_,float angle_,float time_)
    {
        radius = radius_;  //半径
        angle = angle_;     //角度
        time = time_;       //开始运动的时间
    }
}
  • Step2:然后再定义一个粒子系统的变量,粒子的数组和对应的粒子的数据:
private ParticleSystem particleSys;
private ParticleSystem.Particle[] particleArray;
private ParticleData[] particleData;
和一些关于粒子属性的公有的变量,易于调试:
public int count = 10000;       // 粒子数量  
public float size = 0.03f;      // 粒子大小  
public float minRadius = 6.0f;  // 最小半径  
public float maxRadius = 10.0f; // 最大半径  
public bool clockwise = true;   // 顺时针|逆时针  
public float speed = 2f;        // 速度  
public float pingPong = 0.02f;  // 游离范围  
  • Step3:然后在start函数里实例化粒子系统和初始化各粒子的属性与位置:
private void Start()
{

    particleArray = new ParticleSystem.Particle[count];
    particleData = new ParticleData[count];

    particleSys = this.GetComponent<ParticleSystem>();
    particleSys.startSpeed = 0;
    particleSys.startSize = size;
    particleSys.loop = false;
    particleSys.maxParticles = count;
    particleSys.Emit(count);
    particleSys.GetParticles(particleArray);

    setParticlePosition();
}
//初始化粒子位置;
void setParticlePosition()
{
    float midRadius, minRate, maxRate, radius,angle,theta,time;

    for (int i = 0; i < count; i++)
    {
        midRadius = (maxRadius + minRadius) / 2;
        minRate = Random.Range(1.0f, midRadius / minRadius);
        maxRate = Random.Range(midRadius / maxRadius, 1.0f);
        radius = Random.Range(minRadius * minRate, maxRadius * maxRate);
        angle = Random.Range(0.0f, 360.0f);
        theta = angle / 180 * Mathf.PI;
        time = Random.Range(0.0f, 360.0f);

        particleData[i] = new ParticleData(radius,angle,time);
        //particleArray[i].position = new Vector3(particleData[i].radius * Mathf.Cos(theta), 0f, particleData[i].radius * Mathf.Sin(theta));
       particleArray[i].position = new Vector3(particleData[i].radius * Mathf.Cos(theta), particleData[i].radius * Mathf.Sin(theta),0f);
    }
    particleSys.SetParticles(particleArray, particleArray.Length);
}
这一步实现完后如无意外就会显示一个粒子光环了,不过粒子不会动,没有特效而已。   
  • Step4:这一步就是特效的处理了哈哈!旋转原理还是简单的:让每个粒子的角度在每一帧都减少或增加一个值就可以实现旋转了,但这样效果不好,有人说可以加个速度差分层数让不同层的粒子转的速度不一样:
private int diff = 10;  // 师兄博客说是速度差分层数  
private void Update()
{
    float theta;
    for (int i = 0; i < count; i++)
    {
        if (clockwise)
        {
            particleData[i].angle -= (i % diff + 1) * (speed / particleData[i].radius / diff);
        }
        else
        {
            particleData[i].angle += (i % diff + 1) * (speed / particleData[i].radius / diff);
        }
        // 保证angle在到360度,这个方法有点技巧。
        particleData[i].angle = (360.0f + particleData[i].angle) % 360.0f;
        theta = particleData[i].angle / 180 * Mathf.PI;
        particleArray[i].position = new Vector3(particleData[i].radius * Mathf.Cos(theta), particleData[i].radius * Mathf.Sin(theta), 0f);
    }
    particleSys.SetParticles(particleArray, particleArray.Length);
}

然后设置粒子的跳动效果(在上面的for循环里加入这两句):

 particleData[i].time += Time.deltaTime;
 particleData[i].radius += Mathf.PingPong(particleData[i].time / minRadius / maxRadius, pingPong) - pingPong / 2.0f;
  • Step6 :创建一个空对象,命名为ParticleHalo,然后往ParticleHalo物体添加两个空对象,然后给这两个对象添加ParticleSystem组件:

    然后分别改一下myParticle0和myParticle的transfrom属性:

    设置后就可以得到这个效果(静图):

  • Step7:最后加点颜色,用到Gradient类,先加上一个Gradient变量:

public Gradient colorGradient;

然后在Inspector窗口里改变colorGradient的值:

这里写图片描述

然后再增加改变颜色的函数:

void changeColor()
{
    float colorValue;
    for (int i = 0; i < count; i++)
    {
        //改变颜色
        colorValue = (Time.realtimeSinceStartup - Mathf.Floor(Time.realtimeSinceStartup));
        colorValue += particleData[i].angle/360;
        while (colorValue > 1)
            colorValue--;
        particleArray[i].color = colorGradient.Evaluate(colorValue);
    }
}

改完之后在Update里的for嵌套循环里加上执行改变函数的语句:

//Update
changeColor();
  • Step8: 然后就可以得到最终效果了:

总结

  • 粒子流编程不容易啊!也用到了好多数学知识,感谢往年师兄的博客引导,也查了相关色彩变换教程。

附录:相关资料链接:

师兄的博客
色彩变换

阅读更多
换一批

没有更多推荐了,返回首页