首页 > 其他分享 >unity粒子系统——粒子光环

unity粒子系统——粒子光环

时间:2023-01-14 21:22:06浏览次数:60  
标签:粒子系统 angle alphaKeys float unity radius 光环 time circle

由于粒子系统调整各种属性时较为繁杂,所以这次我选择了用代码来控制粒子的方式。

首先创建一个空对象,添加particle System组件,然后新建脚本文件ParticleHalo并将其拖到空对象上。

ParticleHalo创建了10000个粒子,并在初始化和更新函数中调整它们的位置和透明度。

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

public class ParticleHalo : MonoBehaviour

{

    private ParticleSystem particleSys;  // 粒子系统

    private ParticleSystem.Particle[] particleArr;  // 粒子数组

    private CirclePosition[] circle; // 极坐标数组

    public int count = 10000;      // 粒子数量

    public float size = 0.03f;      // 粒子大小

    public float minRadius = 5.0f;  // 最小半径

    public float maxRadius = 12.0f; // 最大半径

    public bool clockwise = false;  // 顺时针|逆时针

    public float speed = 2f;        // 速度

    public float pingPong = 0.02f;  // 游离范围

    // Start is called before the first frame update

    public Gradient colorGradient;

    void Start ()

    { 

        clockwise = false;

        // 初始化粒子数组

        particleArr = new ParticleSystem.Particle[count];

        circle = new CirclePosition[count];

        // 初始化粒子系统

        particleSys = this.GetComponent<ParticleSystem>();

        particleSys.startSpeed = 0;            // 粒子位置由程序控制

        particleSys.startSize = size;          // 设置粒子大小

        particleSys.loop = false;

        particleSys.maxParticles = count;      // 设置最大粒子量

        particleSys.Emit(count);              // 发射粒子

        particleSys.GetParticles(particleArr);

        // 初始化梯度颜色控制器

        GradientAlphaKey[] alphaKeys = new GradientAlphaKey[3];

        alphaKeys[0].time = 0.0f; alphaKeys[0].alpha = 0.0f;

        alphaKeys[1].time = 0.01f; alphaKeys[1].alpha = 1.0f;

        alphaKeys[2].time = 0.99f; alphaKeys[2].alpha = 1.0f;

        // alphaKeys[3].time = 0.6f; alphaKeys[3].alpha = 1.0f;

        // alphaKeys[4].time = 0.9f; alphaKeys[4].alpha = 0.4f;

        // alphaKeys[5].time = 1.0f; alphaKeys[5].alpha = 0.9f;

        GradientColorKey[] colorKeys = new GradientColorKey[2];

        colorKeys[0].time = 0.0f; colorKeys[0].color = Color.white;

        colorKeys[1].time = 1.0f; colorKeys[1].color = Color.white;

        colorGradient.SetKeys(colorKeys, alphaKeys);

        RandomlySpread();  // 初始化各粒子位置

    }

    private int tier = 10;  // 速度差分层数

    public float time = 0f;

    void Update ()

    {

        time = (time + Time.deltaTime > 5 ? 5 : time + Time.deltaTime);

        int appear_count = (int)(time / 5.0f * count);

        for (int i = 0; i < count; i++)

        {

            if (clockwise)  // 顺时针旋转

                circle[i].angle -= (i % tier + 1) * (speed / circle[i].radius / tier);

            else            // 逆时针旋转

                circle[i].angle += (i % tier + 1) * (speed / circle[i].radius / tier);

            // 保证angle在0~360度

            circle[i].angle = (360.0f + circle[i].angle) % 360.0f;

            float theta = circle[i].angle / 180 * Mathf.PI;

            // 粒子在半径方向上游离

            circle[i].time += Time.deltaTime;

            circle[i].radius += Mathf.PingPong(circle[i].time / minRadius / maxRadius, pingPong) - pingPong / 2.0f;

            if (circle[i].radius < circle[i].startRadius) {

                circle[i].radius += 0.001f;

            }

            else {

                circle[i].radius -= 0.001f;

            }

            if (circle[i].radius > maxRadius) {

                circle[i].radius -= 0.01f;

            }

            if (circle[i].radius < minRadius) {

                circle[i].radius += 0.01f;

            }

            // if (circle[i].radius < minRadius) {

            //    circle[i].radius = (maxRadius + minRadius) / 2;

            // }

            particleArr[i].position = new Vector3(circle[i].radius * Mathf.Cos(theta),  circle[i].radius * Mathf.Sin(theta), 0);

            if (i > appear_count) {

                particleArr[i].color = colorGradient.Evaluate(0f);

            }

            else {

                particleArr[i].color = colorGradient.Evaluate(circle[i].angle / 360.0f);

            }



        }



        particleSys.SetParticles(particleArr, particleArr.Length);

    }

    void RandomlySpread()

    {

        for (int i = 0; i < count; ++i)

        {  // 随机每个粒子距离中心的半径,同时希望粒子集中在平均半径附近

            float midRadius = (maxRadius + minRadius) / 2;

            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 radius = (float)i / count * 10f;

            // if (radius == 0) radius = 0.0001f;

            // 随机每个粒子的角度

            //float angle = Random.Range(0.0f, 360.0f);

            float angle = (float)i / count * 360.0f;

            //Debug.Log(angle);

            float theta = angle / 180 * Mathf.PI;

            // 随机每个粒子的游离起始时间

            float time = Random.Range(0.0f, 360.0f);

            circle[i] = new CirclePosition(radius, angle, time, radius);

            particleArr[i].position = new Vector3(circle[i].radius * Mathf.Cos(theta), circle[i].radius * Mathf.Sin(theta), 0f);

        }

        particleSys.SetParticles(particleArr, particleArr.Length);

    }

}

public class CirclePosition

{

    public float radius = 0f, angle = 0f, time = 0f, startRadius = 0f;

    public CirclePosition(float radius, float angle, float time, float startRadius)

    {

        this.radius = radius;  // 半径

        this.angle = angle;    // 角度

        this.time = time;      // 时间

        this.startRadius = startRadius;

    }

}

下文主要讲为了实现光环缩放功能所做的改进。

总体思路还是控制光环的半径,不过这次是同时缩小最大半径和扩大最小半径,实现更强的例子往中间收缩的效果。当半径范围恢复正常后,粒子又应该逐渐回复到最初的状态。上下两个不同的数值体现出当半径范围不同于初始范围时,粒子向新的半径范围移动的趋势大于恢复正常半径的趋势。

if (circle[i].radius < circle[i].startRadius) {

    circle[i].radius += 0.001f;

}

else {

    circle[i].radius -= 0.001f;

}

if (circle[i].radius > maxRadius) {

    circle[i].radius -= 0.01f;

}

if (circle[i].radius < minRadius) {

    circle[i].radius += 0.01f;

}

项目地址:传送门

视频演示:传送门

本次作业借鉴了师兄的博客,感谢。

标签:粒子系统,angle,alphaKeys,float,unity,radius,光环,time,circle
From: https://www.cnblogs.com/qian-L/p/17052569.html

相关文章

  • UnityShader透明效果
    透明效果在实时渲染中要实现透明效果,通常会在渲染模型时控制它的透明通道。当开启透明混合后,当一个物体被渲染到屏幕上时,每个片元除了颜色和深度值之外,它还有另一个属性......
  • 【Unity渲染】一文看懂!Unity通用渲染管线URP介绍
    一、Unity通用渲染管线(URP)Unity的渲染管线包含内置渲染管线、SRP、URP和HDRP。自从Unity2019.3开始,Unity将轻量级渲染管线修改为了通用渲染管线,这是一种快速、可扩展的渲......
  • UnityShader光照基础
    光照基础环境光和自发光环境光:只需通过Unity的内置变量UNITY_LIGHTMODEL_AMBIENT就可以得到环境光的颜色和强度。自发光:把材质的自发光颜色添加到输出颜色上即可。漫......
  • unity 利用相机截图,可以截取UI,保存png格式,可用于签名抠图
    publicCameracam;voidStart(){StartCoroutine(CaptureAlphaCamera(cam,newRect(0,0,1920,1080)));}#region截取透明图///<sum......
  • Unity URP Shader之灰度化
    shader如下:1Shader"TA/Unlit/UI/UIImageGray"2{3Properties4{5_MainTex("MainTexture",2D)="white"{}6}78SubShad......
  • Unity中单例模式的优雅实现
    引言系统地整理了下在Unity中实现单例的几种写法。针对两类情况分别提供了实现方案:纯C#实现(7种)继承自MonoBehaviour(3种)分析了各种方案的优劣,记录了思考过程,最后......
  • VS Code调试Unity程序之2023最新版
    问题换了台开发机,重新安装了下开发环境。突然发现VisualStudioCode无法用来调试Unity了。明明流程都是按照Unity官方教程2023.1进行的,可在创建Launch.json文件时,死活出......
  • Unity中的委托
    目录目录目录基础介绍为什么用委托?源码中的委托用于回调函数用于事件处理其他知识基础介绍在c#中委托是一个类型安全的,面向对象的函数指针。委托的优点是它允许程序员......
  • unityShader入门精要 渲染流水线
    应用阶段把数据加载到显存中设置渲染状态调用DrawCall几何阶段顶点着色器顶点着色器需要完成的工作主要有:坐标变换和逐顶点光照坐标变换:就是对顶点的......
  • 关于Unity的Android工程,写文件的问题
    UnityAndroid工程中的写文件在安卓工程下,写入文件可以直接用:File.WriteAllText(UnityEngine.Application.persistentDataPath+"/XXX.txt","文件内容");路径前面没有加“......