【Unity3D】粒子光环

作业要求


参考http://i-remember.fr/en 这类网站,使用粒子流编程控制制作一些效果, 如“粒子光环”

这个网站打不开,参考了一下师兄们的博客的图片:
在这里插入图片描述
我看了一下,我感觉和上课做的粒子海洋有一些相似,就是需要变成一个环形。

制作流程


粒子光环制作
  • 添加一个空对象,并且添加部件ParticleSystem,然后简单设置一下属性:

在这里插入图片描述
再设置一下Render的属性中的材料。

粒子光环的属性

创建一个脚本ParticleCircle

	public ParticleSystem myparticleSystem;	//粒子系统
    private ParticleSystem.Particle[] particleArray;
    private SingleParticle[] points;
    public Gradient grad;
    int count = 1000;
    public float size = 0.5f;
    public float minRadius = 3.0f;
    public float maxRadius = 6.0f;
    public float speed = 0.5f; // 速度参数

  • ParticleSystem.Particle[] particleArray

粒子数组,保存了每一个粒子的状态,同时规定一个数量count,也就是数组的大小。

  • SingleParticle[] points

记录了每个粒子对于整个光环的状态,两个最重要的属性角度与半径,因为每个粒子都是绕中心点运动,所以运动轨迹会有一个半径,运动到什么地方就需要角度来记录。这里用到自己定义的一个类SingleParticle。

  • Gradient grad

颜色渐变器

  • 粒子大小,光环内径外径,转圈速度,旋转方向等。
粒子的位置属性

定义的一个类SingleParticle:通过角度和半径来估算粒子所在的xy平面的面积,xy坐标就是通过三角函数来计算出来。

public class SingleParticle {
    public float angle;
    public float radius;

    private float x = 0.0f;
    private float y = 0.0f;


    public void CalPosition() {
        float temp = angle / 180.0f * Mathf.PI;
        y = radius * Mathf.Sin(temp);
        x = radius * Mathf.Cos(temp);
    }
    public SingleParticle(float angle, float radius) {
        this.angle = angle;
        this.radius = radius;
    }

    public float getX() {
        return x;
    }

    public float getY() {
        return y;
    }

}
粒子系统初始化
  • 初始化属性:
    void Start () {
        // myparticleSystem = this.GetComponent<ParticleSystem>();
        particleArray = new ParticleSystem.Particle[count];
        points = new SingleParticle[count];
        var m = myparticleSystem.main;
        m.startSpeed = 0;
        m.startSize = size;
        m.maxParticles = count;
        myparticleSystem.Emit(count);
        myparticleSystem.GetParticles(particleArray);

        Init();
    }

  • init的函数就是作为粒子位置的初始化

通过内径和外径,中间划分一个分截,粒子分别在这两个部分中随机分布,角度则是360度随机。

    private void Init() {
        int i;
        for (i = 0; i < count; i++) {
            float midRadius = (minRadius + maxRadius) / 2.0f;
            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);
            points[i] = new SingleParticle(angle, radius);
            points[i].CalPosition();
            particleArray[i].position = new Vector3(points[i].getX(), points[i].getY(), 0f);
        }

        myparticleSystem.SetParticles(particleArray, particleArray.Length);
    }

  • Update

每次更新都需要循环遍历1000个粒子,对于每个粒子的状态都做一次改变,像角度颜色等

  1. 将1000个粒子分为10层,每一层转动的角度(即速度)都略微不一样,然后分成3部分:第一、三部分是同一个方向旋转,第二部分是另一个方向旋转。最后需要对增加后的角度取模,以免溢出360度,或者小于0度。最后算出xy坐标。
  2. 颜色的改变,通过代码来选择其中的颜色,随时间变化,用Gradient渐变器的Evaluate获取对应的颜色,SetParticles函数将这些计算出来的颜色和位置设置到粒子本身中去。
    void Update () {
        int i;
        int level = 10;
        for (i = 0; i < count; i++) {

            if (i % level < 3 || i % level > 6)
            {
                points[i].angle -= rotate_speed * (i % level + 1) * speed;
            } else {
                points[i].angle += rotate_speed * (i % level + 1) * speed;
            }

            points[i].angle = (points[i].angle + 360.0f) % 360.0f; 
            points[i].CalPosition();
            float value = Time.realtimeSinceStartup % 1.0f;
            value -= rotate_speed * points [i].angle /360.0f;
            while (value > 1)
                value--;
            while (value < 0)
                value ++;
            particleArray[i].startColor = grad.Evaluate(value);
            particleArray[i].position = new Vector3(points[i].getX(), points[i].getY(), 0.0f);
        }
        myparticleSystem.SetParticles(particleArray, particleArray.Length);
    }
改进——制作缩放
  • 增加变量
public bool rotate_way = false; // 决定圈扩大还是缩小
private float rotate_speed = -1; // 颜色旋转速度(正负代表方向)
private float time = 0;
  • 修改update函数

总时长为10,然后分成两段,一段是放大,一段是缩小的

	time += Time.deltaTime;
	if (time < 10) {
	    if (time < 5) {
	        rotate_way = false;
	        rotate_speed += 0.01f;
	    }
	    else {
	        rotate_way = true;
	        rotate_speed -= 0.01f;
	    }
	} else {
	    time = 0;
	    rotate_speed = -1;
	}

在对粒子属性的循环中,加入以下代码:

将粒子分成两部分(还是熟悉的配方,不知道为什么这么执迷于分层),然后一部分圈半径改变的速度快一点,一部分改变得慢一点,注意不能差别太大,可能会分层。

	if (i % level > 5) {
	    float tmp = rotate_way? 1 : -1;
	    points[i].radius += tmp * 0.05f;
	}
	if (i % level <= 5) {
	    float tmp = rotate_way? 1 : -1;
	    points[i].radius += tmp * 0.052f;
	}
增加——轨迹

在这里插入图片描述

选择一个材料:
在这里插入图片描述

游戏效果


是一个自动放大缩小、三层粒子以不同速度和方向运动且带有轨迹的粒子光环。
(这里是静态图,不太会搞动图)
在这里插入图片描述

后记


这一次的代码比较容易,需要注意的是分层单独设置的部分,要做出那种类似粒子海洋的涌动那种感觉。

github地址

参考博客

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值