Unity 3d 粒子系统制作

使用Unity 3d 制作粒子光环和海洋

效果图
在这里插入图片描述
共有三个粒子系统对象和对应的脚本,图中有两个光环和粒子海洋,期中红色圈是内环,外环的颜色是不断变化的且成顺时针方向转动,海洋在两个光环靠后的位置进行运动。

光环的思路:如何让粒子呈环状分布? 使用三角函数,对特定的圆心位置和半径,,rsin(弧度)就是该粒子的y轴坐标,rcos(弧度)为x轴坐标,z轴就置零。因为这是一个环,有最小半径和最大半径,因此r要在这之间取随机数,而角度就360内都行(最后要转换成弧度制)。然后在里面的特效中的粒子应该是有顺时针也有逆时针的,这个我用奇偶数来实现,偶数顺时针,奇数逆时针。

两个光环的参数附图:
外渐变环:
在这里插入图片描述
内部红环:
在这里插入图片描述
粒子海洋的思路:
创建粒子系统和储存粒子海洋的数组,分配粒子的位置并创建柏林噪声,柏林噪声可以基于x轴和y轴产生对应的z轴输出,用于控制粒子海洋中的柏林噪声,是使所有元素流畅的做循环运动很重要的一环,最后设置颜色等参数,
粒子海洋参数如下:
在这里插入图片描述

具体制作步骤:

1.生成对应的粒子系统对象
在这里插入图片描述
2.调整颜色和位置等参数,以及Particle System中三个重要模块的参数如Duration和Emission Rate over time等粒子的存活时间和生成速率等。
(参数图已在上面展示)
3.新建脚本来控制三个粒子系统中粒子运动,先是对两个光环运动控制的脚本particleRing和Particle 。
外渐变颜色的光环
Start 用 GetComponent()获取粒子系统对象部件ps并初始化x,y 方向,然后Update运动函数判断现在ps的位置和方向来进行调整运动方向矢量,做圆周循环运动。代码如下

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

public class particleRing : MonoBehaviour
{
    public ParticleSystem ps;
    int directionx,directiony;

    void Start() {
        ps= GetComponent<ParticleSystem>();
        directionx = 0;
        directiony = 0;
    }
 
    void Update() {
        int minX = -10, maxX = 10 ;
        if (directionx == 0 && ps.transform.position.x > minX){
            ps.transform.position += Vector3.left * Time.deltaTime * 50;
            Vector3 tmp=ps.transform.position;
            double numy=100.0f-(ps.transform.position.x*ps.transform.position.x);
            if(numy<0) numy=0;
            else numy=Math.Sqrt(numy);
            if(directiony==0) numy=numy*-1;
            tmp.y=(float)numy;
            ps.transform.position=tmp;
        } else if (directionx == 1 && ps.transform.position.x < maxX){
            ps.transform.position += Vector3.right * Time.deltaTime * 50;
            Vector3 tmp=ps.transform.position;
            double numy=100.0f-(ps.transform.position.x*ps.transform.position.x);
            if(numy<0) numy=0;
            else numy=Math.Sqrt(numy);
            if(directiony==0) numy=numy*-1;
            tmp.y=(float)numy;
            ps.transform.position=tmp;
        } else{
            directionx=1-directionx;
            directiony=1-directiony;
        }
    }
}

内环设置不同速度档次和方向的粒子,并且设置在最大半径和最小半径之间的随机半径,从而表现光环的伸缩趋势。Start初始化梭鱼要 的一众参数,如数组和最大数量等,并且为每个粒子设置其位置,随机化生成角度和半径,且在Update中通过鼠标点击事件move可以调整运动速度,代码逻辑如下:

using UnityEngine;
using System.Collections;

public class Particle : MonoBehaviour
{

    ParticleSystem particleSystem;
    private ParticleSystem.Particle[] particlesArray;
    public int particleNumber = 700;
    public float radius = 2.0f;
    public float midR = 5.5f;
    public float maxR = 8.5f;
    public float free = 1.5f;//设置游动的范围  

    public float[] particleAngle;
    public float[] particleRadius;
    public float time = 0;
    GameObject gameObject_;
    bool move = true;
    public float speed = 0.15f;
    void Start()
    {
        particleSystem = GetComponent<ParticleSystem>();
        particlesArray = new ParticleSystem.Particle[particleNumber];//将储存粒子的数组初始化
        particleSystem.maxParticles = particleNumber;//设置粒子发射的最大数量
        particleAngle = new float[particleNumber];
        particleRadius = new float[particleNumber];

        particleSystem.Emit(particleNumber);//将刚刚初始化的particleNumber个粒子发射出去
        particleSystem.GetParticles(particlesArray);
        for (int i = 0; i < particleNumber; i++)
        {//为每个粒子设置其位置
            //最小半径随机扩大
            float rate1 = Random.Range(1.0f, midR / radius);
            //最大半径随机缩小
            float rate2 = Random.Range(midR / maxR, 1.0f);
            float r = Random.Range(radius * rate1, maxR * rate2);
            //float r = Random.Range(radius, 6.0f);
            float angle = Random.Range(0.0f, 360.0f);//位置为0 - 360度的随机一个角度
            float rad = angle / 180 * Mathf.PI;//角度变换成弧度

            particleRadius[i] += Mathf.PingPong(time, free) - free / 2.0f;
            time += Time.deltaTime;

            particleAngle[i] = angle;
            particleRadius[i] = r;
            particlesArray[i].position = new Vector3(r * Mathf.Cos(rad), r * Mathf.Sin(rad), 0.0f);//为每个粒子坐标赋值 
        }
        particleSystem.SetParticles(particlesArray, particlesArray.Length);//设置该粒子系统的粒子。前面数组的长度是设置粒子的数量
    }
    void Update()
    {
        //   Debug.Log(move);
        if (move)
        {
            for (int i = 0; i < particleNumber; i++)
            {
                //设置速度为五个不同的档次
                if (i % 2 == 0)
                {
                    particleAngle[i] += speed * (i % 80 + 1);
                }
                else
                {
                    particleAngle[i] -= speed * (i % 80 + 1);
                }
                if (particleAngle[i] > 360)
                    particleAngle[i] -= 360;
                if (particleAngle[i] < 0)
                    particleAngle[i] += 360;
                float rad = particleAngle[i] / 180 * Mathf.PI;
                particlesArray[i].position = new Vector3(particleRadius[i] * Mathf.Cos(rad), particleRadius[i] * Mathf.Sin(rad), 0f);
            }
            particleSystem.SetParticles(particlesArray, particleNumber);
        }
        //Debug.Log("111");
    }

    private void OnMouseDown()
    {


        if (move)
        {
            move = false;

        }
        else
        {
            move = true;

        }

    }
}


粒子海洋

SeaParticle.cs
创建粒子数组particleArray ,设置颜色变量Gradient和粒子海洋
每行的数目以及粒子之间的间隔还有柏林噪声的参数。
Start 函数中对这些变量进行初始化并且分布位置,其中中关键点 zPos(通过柏林噪声函数赋值)Update让粒子运动起来,让粒子在x,z 方向上进行波动,并且重新设置x,y 的值从而实现波动,然后更信位置和参数。

在这里插入代码片
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SeaParticle : MonoBehaviour
{
    public ParticleSystem particleSystem;
    private ParticleSystem.Particle[] particlesArray;
    public Gradient colorGradient;
    public int seaResolution = 50; //每行粒子的数目
    public float spacing = 0.5f;//粒子之间的间隔
    public float noiseScale = 0.2f; //
    public float heightScale = 3f;
    public float noiseX;
    public float noiseY;
    // Use this for initialization
    void Start()
    {
        particleSystem = GetComponent<ParticleSystem>();
        particleSystem.loop = false;
        particlesArray = new ParticleSystem.Particle[seaResolution * seaResolution];
        particleSystem.maxParticles = seaResolution * seaResolution;
        particleSystem.Emit(seaResolution * seaResolution);
        particleSystem.GetParticles(particlesArray);
        for (int i = 0; i < seaResolution; i++)
        {
            for (int j = 0; j < seaResolution; j++)
            {

                float zPos = Mathf.PerlinNoise(i * noiseScale, j * noiseScale) * heightScale;
                particlesArray[i * seaResolution + j].position = new Vector3(i * spacing, zPos, j * spacing);
            }
        }
        particleSystem.SetParticles(particlesArray, particlesArray.Length);
    }

    // Update is called once per frame
    void Update()
    {
        for (int i = 0; i < seaResolution; i++)
        {
            for (int j = 0; j < seaResolution; j++)
            {

                float zPos = Mathf.PerlinNoise(i * noiseScale + noiseX, j * noiseScale + noiseY);
                //让粒子在x、z方向上波动
                float r = Random.Range(5, 10);
                particlesArray[i * seaResolution + j].color = colorGradient.Evaluate(zPos);

                //重新设置x,y的原因是为了让粒子波动起来
                particlesArray[i * seaResolution + j].position = new Vector3((i + zPos * r) * spacing, zPos * heightScale, (j + zPos * r) * spacing);
            }
        }
        particleSystem.SetParticles(particlesArray, particlesArray.Length);
        noiseX += Time.deltaTime;
        noiseY += Time.deltaTime;
    }
}

演示效果视频
https://www.bilibili.com/video/BV1o3411m7FT/?spm_id_from=333.999.0.0&vd_source=66cc21f92131571125d69a5f24344dcd
项目地址
https://github.com/circle-fish/particle-system

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值