八、粒子系统与流动效果

制作粒子光环

概述

粒子光环由内外两层粒子构成。外层粒子分布范围更广,旋转速度更快。内层粒子分布范围窄,旋转速度更慢。

对象制作

创建一个空对象Halo,附加两个子对象Inner和Outer,分别给两个子对象添加Particle System 组件。设置如下
在这里插入图片描述

代码设计

HaloParticleData.cs

粒子的数据类,记录粒子距离圆心的半径和角度

public class HaloParticleData {
    public HaloParticleData(float r = 0, float a = 0) {
        radius = r;
        angle = a;
    }
    public float radius {
        get;
        set;
    }
    public float angle {
        get;
        set;
    }
}

InnerHalo.cs

  • 初始化粒子系统
    设置每个粒子的半径和角度值,确定粒子的位置。
    用一个布尔值标记当前粒子的缩放方向,两个半径数组规定缩放范围。
public class InnerHalo : MonoBehaviour
{
    public ParticleSystem particleSystem;// 粒子系统
    private ParticleSystem.Particle[] particleArray;// 粒子数组
    private int haloResolution = 3500;// 粒子数量
    private float minRadius = 2.5F;// 最小半径
    private float maxRadius = 4F;// 最大半径
    private HaloParticleData[] haloParticledata;//粒子数据
    private float shrinkSpeed = 0.5f;//缩放速度       
    private float[] max;// 扩张后粒子半径
    private float[] min;// 收缩后粒子半径
    private bool direction = true; //T-收缩 F-扩张
    // Start is called before the first frame update
    void Start()
    {
        particleSystem = this.GetComponent<ParticleSystem>();
        particleArray = new ParticleSystem.Particle[haloResolution];
        haloParticledata = new HaloParticleData[haloResolution];
        max = new float[haloResolution];
        min = new float[haloResolution];

        particleSystem.Emit(haloResolution);
        particleSystem.GetParticles(particleArray);
        for (int i = 0; i < haloResolution; ++i)
        {
            float shiftMinRadius = Random.Range(1, (maxRadius + minRadius) / 2 / minRadius);
            float shiftMaxRadius = Random.Range((maxRadius + minRadius) / 2 / maxRadius, 1);
            float radius = Random.Range(minRadius * shiftMinRadius, maxRadius * shiftMaxRadius);
            max[i] =  radius+1;
            min[i] =  radius-1;
            float angle = Random.Range(0, Mathf.PI * 2);

            haloParticledata[i] = new HaloParticleData(radius, angle);
            particleArray[i].position = new Vector3(radius * Mathf.Cos(angle), radius * Mathf.Sin(angle), 0);
        }
        particleSystem.SetParticles(particleArray, particleArray.Length);
    }
}

  • 粒子系统运动
    在update函数中更新粒子角度值和半径,重新计算粒子位置,实现粒子的圆周运动以及循环缩放。
    到达缩放限值后调转方向。
    void Update()
    {
        for (int i = 0; i < haloResolution; ++i)
        {
            haloParticledata[i].angle -= Random.Range(0, 1F / 360) / 2;

            if (direction)
            {
                if (haloParticledata[i].radius > min[i]) haloParticledata[i].radius -= shrinkSpeed *  Time.deltaTime;
                else direction = false;
            }
            else
            {
                if (haloParticledata[i].radius < max[i]) haloParticledata[i].radius += shrinkSpeed *  Time.deltaTime;
                else direction = true;
            }

            float angle = haloParticledata[i].angle;
            float radius = haloParticledata[i].radius;
            particleArray[i].position = new Vector3(radius * Mathf.Cos(angle), radius * Mathf.Sin(angle), 0);
        }
        particleSystem.SetParticles(particleArray, particleArray.Length);
    }

OuterHalo.cs

外层的代码和内层基本相同,只需修改几个参数,修改粒子数目,半径范围和旋转速度即可。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class OuterHalo : MonoBehaviour
{
    public ParticleSystem particleSystem;// 粒子系统
    private ParticleSystem.Particle[] particleArray;// 粒子数组
    private int haloResolution = 3000;// 粒子数量
    private float minRadius = 2F;// 最小半径
    private float maxRadius = 4.5F;// 最大半径
    private HaloParticleData[] haloParticledata;//粒子数据
    private float shrinkSpeed = 0.5f;//缩放速度       
    private float[] max;// 扩张后粒子半径
    private float[] min;// 收缩后粒子半径
    private bool direction = true; //T-收缩 F-扩张
    // Start is called before the first frame update
    void Start()
    {
        particleSystem = this.GetComponent<ParticleSystem>();
        particleArray = new ParticleSystem.Particle[haloResolution];
        haloParticledata = new HaloParticleData[haloResolution];
        max = new float[haloResolution];
        min = new float[haloResolution];

        particleSystem.Emit(haloResolution);
        particleSystem.GetParticles(particleArray);
        for (int i = 0; i < haloResolution; ++i)
        {
            float shiftMinRadius = Random.Range(1, (maxRadius + minRadius) / 2 / minRadius);
            float shiftMaxRadius = Random.Range((maxRadius + minRadius) / 2 / maxRadius, 1);
            float radius = Random.Range(minRadius * shiftMinRadius, maxRadius * shiftMaxRadius);
            max[i] =  radius+1;
            min[i] =  radius-1;
            float angle = Random.Range(0, Mathf.PI * 2);

            haloParticledata[i] = new HaloParticleData(radius, angle);
            particleArray[i].position = new Vector3(radius * Mathf.Cos(angle), radius * Mathf.Sin(angle), 0);
        }
        particleSystem.SetParticles(particleArray, particleArray.Length);
    }

    // Update is called once per frame
    void Update()
    {
        for (int i = 0; i < haloResolution; ++i)
        {
            haloParticledata[i].angle -= Random.Range(0, 1F / 360);

            if (direction)
            {
                if (haloParticledata[i].radius > min[i]) haloParticledata[i].radius -= shrinkSpeed  * Time.deltaTime;
                else direction = false;
            }
            else
            {
                if (haloParticledata[i].radius < max[i]) haloParticledata[i].radius += shrinkSpeed  * Time.deltaTime;
                else direction = true;
            }
            
            float angle = haloParticledata[i].angle;
            float radius = haloParticledata[i].radius;
            particleArray[i].position = new Vector3(radius * Mathf.Cos(angle), radius * Mathf.Sin(angle), 0);
        }
        particleSystem.SetParticles(particleArray, particleArray.Length);
    }
}

效果展示

在这里插入图片描述
(建议屏幕亮度调高)

代码传送门

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值