Unity学习记录——粒子系统与流动效果

2023-11-13

Unity学习记录——粒子系统与流动效果

前言

​ 本文是中山大学软件工程学院2020级3d游戏编程与设计的最终作业

编程题:粒子光环

1.概述

​ 粒子系统在unity官网与老师课件中的概念定义如下:

粒子系统 - Unity 手册:一个粒子系统可以模拟并渲染许多称为粒子的小图像或网格以产生视觉效果。系统中的每个粒子代表效果中的单个图形元素。系统共同模拟每个粒子以产生完整效果的印象。

粒子系统与流动效果 | 3D Game Programming & Design (pmlpml.github.io):粒子系统是模拟一些不确定、流动现象的技术。它采用许多形状简单且赋予生命的微小粒子作为基本元素来表示物体(一般由点或很小的多边形通过纹理贴图表示),表达物体的总体形态和特征的动态变化。人们经常使用粒子系统模拟的现象有火、爆炸、烟、水流、火花、落叶、云、雾、雪、尘、流星尾迹或者象发光轨迹这样的抽象视觉效果等等。

2.题目要求

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

​ 最终作业附加要求:必须带一个控制组件,控制粒子呈现效果

3.操作

​ 按照如下结构建立一个对象HaloSystem

​ 其中:

  • HaloSystem为Empty,作为承载粒子系统的父类
  • Collider为Empty,挂在了粒子系统所需要的碰撞体
  • halo为Empty,用于作为粒子系统的父类
  • in和out都为Particle System,即粒子系统,本次粒子系统的主角,通过两者不同地方的设置呈现效果

请添加图片描述

​ 建立好HaloSystem首先给Collider添加碰撞体,设置如下:

请添加图片描述

​ 分别将in和out两个粒子系统的数值修改如下:

请添加图片描述

​ 对于此处冗长的设置,根据粒子系统模块 - Unity 手册,此处介绍粒子系统的中我们勾选了的模块:

  1. Particle System 模块

    包含影响整个系统的全局属性。大多数这些属性用于控制新创建的粒子的初始状态。其中各个属性如下:

属性 功能
Duration 系统运行的时间长度。
Looping 如果启用此属性,系统将在其持续时间结束时再次启动并继续重复该循环。
Prewarm 如果启用此属性,系统将初始化,就像已经完成一个完整周期一样(仅当 Looping 也启用时才有效)。
Start Delay 启用此属性后,系统开始发射前将延迟一段时间(以秒为单位)。
Start Lifetime 粒子的初始生命周期。
Start Speed 每个粒子在适当方向的初始速度。
3D Start Size 如果要分别控制每个轴的大小,请启用此属性。
Start Size 每个粒子的初始大小。
3D Start Rotation 如果要分别控制每个轴的旋转,请启用此属性。
Start Rotation 每个粒子的初始旋转角度。
Flip Rotation 使一些粒子以相反的方向旋转。
Start Color 每个粒子的初始颜色。
Gravity Modifier 缩放 Physics 窗口中设置的重力值。值为零会关闭重力。
Simulation Space 控制粒子的运动位置是在父对象的局部空间中(因此与父对象一起移动)、在世界空间中还是相对于自定义对象(与您选择的自定义对象一起移动)。
Simulation Speed 调整整个系统更新的速度。
Delta Time ScaledUnscaled 之间进行选择,其中的 Scaled 使用 Time 窗口中的 Time Scale 值,而 Unscaled 将忽略该值。此属性对于出现在暂停菜单 (Pause Menu) 上的粒子系统非常有用。
Scaling Mode 选择如何使用变换中的缩放。设置为 HierarchyLocalShape。Local 仅应用粒子系统变换缩放,忽略任何父级。Shape 模式将缩放应用于粒子起始位置,但不影响粒子大小。
Play on Awake 如果启用此属性,则粒子系统会在创建对象时自动启动。
Emitter Velocity Choose how the Particle System calculates the velocity used by the Inherit Velocity and Emission modules. The system can calculate the velocity using a Rigidbody component, if one exists, or by tracking the movement of the Transform component. If no Rigidbody component exists, the system uses its Transform component by default.
Max Particles 系统中同时允许的最多粒子数。如果达到限制,则移除一些粒子。
Auto Random Seed 如果启用此属性,则每次播放时粒子系统看起来都会不同。设置为 false 时,每次播放时系统都完全相同。
Random Seed 禁用自动随机种子时,此值用于创建唯一的可重复效果。
Stop Action 当属于系统的所有粒子都已完成时,可使系统执行某种操作。当一个系统的所有粒子都已死亡,并且系统存活时间已超过 Duration 设定的值时,判定该系统已停止。对于循环系统,只有在通过脚本停止系统时才会发生这种情况。
Disable 禁用游戏对象。
Destroy 销毁游戏对象。
Callback 将 OnParticleSystemStopped 回调发送给附加到游戏对象的任何脚本。
Culling Mode 选择粒子在屏幕外时是否暂停粒子系统模拟。在屏幕外时进行剔除具有最高效率,但您可能希望继续进行非一次性 (off-one) 效果的模拟。
Automatic 循环系统使用 Pause__,而所有其他系统使用Always Simulate
Disabled 禁用 Ring Buffer Mode__,以便系统在粒子生命周期终结时删除粒子。 | | Pause Until Replaced | 在粒子生命周期结束时暂停旧粒子,直至达到 Max Particle__ 限制,此时系统会进行粒子再循环,因此旧粒子会重新显示为新粒子。
Loop Until Replaced 在粒子生命周期结束时,粒子将倒回到其生命周期的指定比例,直至达到 Max Particle 限制,此时系统会进行粒子再循环,因此旧粒子会重新显示为新粒子。
  1. Emission 模块:模块中的属性会影响粒子系统发射的速率和时间。
  2. Shape模块:该模块定义发射粒子的体积或表面,以及起始速度的方向。Shape 属性定义发射体积的形状,其余模块属性因选择的形状而异。
  3. Renderer模块:决定了粒子的图像或网格如何被其他粒子变换、着色和过度绘制。

​ 之后就是编写代码以及挂载的事情了。

4.代码

​ 代码部分参考了老师给的学长优秀作品:2016 粒子光环:大神神作,无人超

​ 粒子光环的思路很简单,也就是粒子在一个圆环之中向着一个方向运动;当鼠标移动到圆环中心点(之前设置的Collider)时,圆环就为向中心收缩。

  • CirclePosition类,用于记录光环的位置与大小信息,以及时间
public class CirclePosition
{
    public float radius = 0f, angle = 0f, time = 0f;
    public CirclePosition(float radius, float angle, float time)
    {
        this.radius = radius;   // 半径
        this.angle = angle;     // 角度
        this.time = time;       // 时间
    }
}
  • 各种记录光环的各种信息
private ParticleSystem particleSys;                             // 粒子系统
private ParticleSystem.Particle[] particleArr;                  // 粒子数组
private CirclePosition[] circle;                                // 极坐标数组
public int pCount = 5000;                                       // 粒子数量
public float pSize = 0.15f;                                     // 粒子大小
public float minRadius = 4.0f;                                  // 最小半径
public float maxRadius = 11.0f;                                 // 最大半径
public bool clockwise = true;                                   // 旋转方向
public float speed = 1f;                                        // 速度
public float pingPong = 0.01f;                                  // 游离范围
public int tier = 10;                                           // 速度差分层数

public Camera camera;                                           // 主摄像机
private Ray ray;                                                // 射线
private RaycastHit hit;                                         // 碰撞信息
private float[] before;                                         // 收缩前粒子位置
private float[] after;                                          // 收缩后粒子位置
public float shrinkSpeed = 5f;                                  // 粒子缩放的速度
private bool ischange = false;                                  // 是否收缩
public int type;                                                // 光环类型
public Gradient colorGradient;                                  // 颜色渐变
private GradientAlphaKey[] alphaKeys;                           // 透明度
private GradientColorKey[] colorKeys;                           // 颜色
  • 粒子的游离运动函数
void RandomlySpread()
{
    // 初始化各粒子位置
    // 随机每个粒子距离中心的半径,同时希望粒子集中在平均半径附近
    for (int i = 0; i < pCount; ++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 angle = Random.Range(0.0f, 360.0f);
        float theta = angle / 180 * Mathf.PI;
        // 随机每个粒子的游离起始时间
        float time = Random.Range(0.0f, 360.0f);
        circle[i] = new CirclePosition(radius, angle, time);
        before[i] = radius;
        after[i] = 0.7f * radius;
        if (after[i] < minRadius * 1.1f)
        {
            after[i] = Random.Range(Random.Range(minRadius, midRadius), (minRadius * 1.1f));
        }
        particleArr[i].position = new Vector3(circle[i].radius * Mathf.Cos(theta), 0f, circle[i].radius * Mathf.Sin(theta));
    }
    particleSys.SetParticles(particleArr, particleArr.Length);
}
  • Update函数,每一帧检测碰撞事件,此处为光环的收缩与还原的控制
void Update()
{
    for (int i = 0; i < pCount; i++)
    {
        if (ischange)
        {
            // 开始收缩
            if (circle[i].radius > after[i])
            {
                circle[i].radius -= shrinkSpeed * (circle[i].radius / after[i]) * Time.deltaTime;
            }
        }
        else
        {
            // 开始还原
            if (circle[i].radius < before[i])
            {
                circle[i].radius += shrinkSpeed * (before[i] / circle[i].radius) * Time.deltaTime;
            }
        }
        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, pingPong) - pingPong / 2.0f;

        //particleArr[i].startColor = colorGradient.Evaluate(circle[i].angle / 360.0f);
        particleArr[i].position = new Vector3(circle[i].radius * Mathf.Cos(theta), 0f, circle[i].radius * Mathf.Sin(theta));
    }
    ChangeColor();
    particleSys.SetParticles(particleArr, particleArr.Length);

    // 碰撞检测
    ray = camera.ScreenPointToRay(Input.mousePosition);
    if (Physics.Raycast(ray, out hit) && hit.collider.gameObject.tag == "button") ischange = true;
    else ischange = false;
}
  • Start,初始化函数,此处根据设定的类型给光环设置颜色
void Start()
{
    particleArr = new ParticleSystem.Particle[pCount];
    circle = new CirclePosition[pCount];
    before = new float[pCount];
    after = new float[pCount];

    // 初始化粒子系统
    particleSys = this.GetComponent<ParticleSystem>();
    var main = particleSys.main;
    main.startSpeed = 0;
    main.startSize = pSize;
    main.loop = false;
    main.maxParticles = pCount;                                  // 粒子数量               
    particleSys.Emit(pCount);                                    // 发射粒子
    particleSys.GetParticles(particleArr);

    alphaKeys = new GradientAlphaKey[5];
    colorKeys = new GradientColorKey[2];

    // 初始化梯度颜色控制器
    alphaKeys[0].time = 0.0f; alphaKeys[0].alpha = 0.2f;
    alphaKeys[1].time = 0.25f; alphaKeys[1].alpha = 1f;
    alphaKeys[2].time = 0.5f; alphaKeys[2].alpha = 0.2f;
    alphaKeys[3].time = 0.75f; alphaKeys[3].alpha = 1f;
    alphaKeys[4].time = 1.0f; alphaKeys[4].alpha = 0.2f;

    if (clockwise)
    {
        colorKeys[0].time = 0.25f;
        colorKeys[1].time = 0.75f;
        switch (type)   // 根据设定的颜色组合改变
        {
            case 1:
                colorKeys[0].color = new Color(221f / 255, 49f / 255, 221f / 255);
                colorKeys[1].color = new Color(24f / 255, 177f / 255, 224f / 255);
                break;
            case 2:
                colorKeys[0].color = new Color(255 / 255, 30 / 255, 57 / 255);
                colorKeys[1].color = new Color(24f / 255, 224f / 255, 43f / 255);
                break;
        }
    }
    else
    {
        colorKeys[0].time = 0.25f;
        colorKeys[1].time = 0.75f;
        switch (type)
        {
            case 1:
                colorKeys[1].color = new Color(221f / 255, 49f / 255, 221f / 255);
                colorKeys[0].color = new Color(24f / 255, 177f / 255, 224f / 255);
                break;
            case 2:
                colorKeys[1].color = new Color(255 / 255, 30 / 255, 57 / 255);
                colorKeys[0].color = new Color(24f / 255, 224f / 255, 43f / 255);
                break;
        }
    }
    colorGradient.SetKeys(colorKeys, alphaKeys);
    RandomlySpread();
}

5.补充

​ 完善代码之后将代码挂载到粒子系统上,数值设置如下:

  • in

请添加图片描述

  • out

请添加图片描述

​ 之后我们可以将halo再复制一份,增加到HaloSystem中

请添加图片描述

​ 修改MinRadius与Max Radius的大小,再增加颜色种类,呈现多光环的效果

请添加图片描述

​ 最后,修改摄像头的背景,改为全黑色,就可以明显看到粒子效果了

请添加图片描述

演示

​ gif图如下:

​ 由于超出csdn文件大小限制,见gitee

​ 演示视频已经上传至B站unity粒子系统——简单粒子光环_哔哩哔哩_bilibili

代码位置

​ 代码以及文档均已经上传至hw_fina· XiaoChen04_3/3D_Computer_Game_Programming - gitee

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Unity学习记录——粒子系统与流动效果 的相关文章

  • Unbutn20+cuda11+Qt下配置

    首先装CUDA 具体查看其它博客 这里主要介绍如何配置 CONFIG console TARGET test Define output directories CUDA OBJECTS DIR This makes the cu file
  • 面了个阿里拿36K出来的,真是砂纸擦屁股,给我漏了一手

    今年的春招已经结束 很多小伙伴收获不错 拿到了心仪的 offer 各大论坛和社区里也看见不少小伙伴慷慨地分享了常见的面试题和八股文 为此咱这里也统一做一次大整理和大归类 这也算是划重点了 俗话说得好 他山之石 可以攻玉 多看多借鉴还是有帮助
  • js实现图片预加载

    什么是预加载 当页面打开图片提前加载 而且缓存在用户本地 需要用届时直接进行烘托 在浏览图片较多的网页 百度图库 淘宝京东等 能够有更好的用户体会 一张图片的预加载 var img new Image img addEventListene
  • pandas 导入excel_小白学 Python 数据分析(7):Pandas (六)数据导入

    人生苦短 我用 Python 前文传送门 小白学 Python 数据分析 1 数据分析基础 小白学 Python 数据分析 2 Pandas 一 概述 小白学 Python 数据分析 3 Pandas 二 数据结构 Series 小白学 P
  • echarts 生成的canvas只有100px的问题

    在开发中遇到一个问题 使用echarts的时候 生成的canvas宽度不是实际写入的宽度 后面发现 因为使用了el tabs 存在echarts的tab页在刚开始处于display none 所以echarts拿不到页面的宽度 解决办法 在
  • Burp suite ——爆破账户密码(含爆破token防爆破)

    此文章仅供交流学习使用 目录 爆破普通账户密码 设置环境 处理burp suite的抓包数据 开始爆破 爆破token防爆破账户密码 设置环境 处理抓包数据 开始爆破 爆破普通账户密码 设置环境 1 打开火狐访问此网站 更改代理 火狐浏览器

随机推荐

  • 【RocketMQ】消息重试、重试次数设置、死信队列

    文章目录 1 死信队列 1 1 死信特性 1 2 查看死信消息 2 重试次数参数 2 1 Producer端重试 2 2 Consumer端重试 3 1 异常重试 3 2 超时重试 参考 1 死信队列 上一篇 RocketMQ 消息重试中我
  • OpenCL并行编程基础 第六章 OpenCL事件和队列

    任务队列允许程序员通过编辑直接创建 管理和调度任务 队列中的命令按提交命令的顺序执行 队列中的吓一跳命令必须等待当前命令执行完后才能开始执行 不同命令队列的先后执行顺序得不到保证 6 1 命令 命令队列和事件 命令队列保证FIFO 启动顺序
  • The selected directory is not a valid home for Go SDK

    在GoLand中配置GOROOT的时候 出现该错误 The selected directory is not a valid home for Go SDK Go的版本是1 4 2 GoLand 版本是2021 1 3 可能是版本问题 更
  • 自媒体如何使用ChatGPT提高效率

    文章目录 自媒体公司如何充分利用ChatGPT提高效率 自媒体公司使用ChatGPT提高效率的具体案例 训练ChatGPT 让它更懂你 创作者 全栈弄潮儿 个人主页 全栈弄潮儿的个人主页 个人社区 欢迎你的加入 全栈弄潮儿的个人社区 专栏地
  • agg函数加入进度条

    在panda之中 我们经常需要使用到agg函数来将pandas之中的某几列聚合起来 from tqdm import tqdm import pandas as pd import numpy as np df pd DataFrame A
  • 【软件构造】黑盒测试与白盒测试

    文章目录 前言 一 黑盒测试 1 什么是黑盒测试 2 常见的黑盒测试技术 3 等价类划分 a 主要思想 b 有效等价类与无效等价类 c 例子 3 边界值分析 主要思想 4 错误推测法 a 定义 b 主要思想 c 常见的方法 5 因果图 二
  • FPGA和IC设计怎么选?哪个发展更好?

    很多人纠结FPGA和IC设计怎么选 其实往小了说 要看你选择的具体是哪个方向岗位 往大了说 将来你要是走更远 要成为大佬 那基本各个方向的都要有涉及的 不同方向就有不同的发展 目前在薪资上IC设计要比FPGA要高一点 但每个行业都有大佬 薪
  • TCP/IP详解 卷1:协议 学习笔记 第二十五章 SNMP:简单网络管理协议

    随着网络技术的发展 网络数量越来越多 网络中的设备来自不同厂家 如何管理这些设备变得十分重要 基于TCP IP的网络管理包含两个部分 网络管理站 也叫管理进程 manager 和被管理的网络单元 也叫被管设备 包括路由器 X终端 终端服务器
  • USB 供电问题

    原先开发的外接USB设备 每次都要先上电再插到PC上能正常显示 如果设备事先没有上电再插到电脑上然后再给设备上电 PC是无法识别这个USB设备的 之前公司的人一直认为是我固件的问题 最近开发了内置USB设备 结果同样的问题出现了 我索性看了
  • 用于缺陷检测的高分辨率图像的切片处理——工作总结

    目录 参考 背景 原理 切片 标签映射 代码 结果 切片检测结果映射回原图 LabelImg的使用 安装 运行 标注 总结 参考 1 https blog csdn net zengwubbb article details 1158004
  • JS 利用 Set 对数组中对象进行去重

    JS中怎么对一个数组进行去重 相信很多人对这个问题都已经很熟悉了 最简便的方法就是使用 Set let arr 1 2 3 3 4 5 5 console log new Set arr 1 2 3 4 5 那么如何对数组中的对象进行去重呢
  • 刷脸创新技术赋予传统零售智慧发展能力

    其中技术进步起到颠覆性的作用 传统零售商积极拥抱科技进行数字化转型升级 大数据人工智能 人脸识别数据中台等创新技术进入了应用爆发期 与零售产业深度融合 加速零售在经营管理销售 服务等方面优化升级 创新技术赋予了传统零售业智慧发展的能力 在新
  • HTML的段落中怎么样显示出标签要使用的尖括号<>?

    很简单 符号 lt 用 lt 替代 符号 gt 用 gt 替代 示例代码如下 h4 HTML中怎样打出尖括号 h4 p 左尖括号 lt p p 右尖括号 gt p p p 运行效果如下
  • DVWA-xss全等级教程

    low等级 反射型 reflected 在输入框随便输入一串字符 跟踪字符发现其出现在 pre 标签中 于是可以通过自建标签方式进行弹框 这里输入来实现弹框 当然还能输入 img src xx 也可以通过输入 pre
  • Pycharm + anaconda 安装第三方库总是提醒安装失败或者安装包后import失败

    原因 1 pycharm 新建项目后 随项目建立的虚拟环境没有被激活 2 如果用pip安装 有可能是pip没有更形 3 用anaconda安装 有可能是anaconda没有更新 4 第三方库的所在位置不是pycharm项目对应虚拟环境的未知
  • 六、Pytest自动化测试框架 — Pytest预期失败

    文章内容有配套的 学习视频和笔记都放在了文章末尾 Pytest预期失败需要使用 pytest mark xfail 标记 1 pytest mark xfail 标记的作用 期望测试用例是失败的 但是会运行此测试用例 并且也不会影响其他测试
  • hive报错:return code 1 from org.apache.hadoop.hive.ql.exec.DDLTask. MetaException(message:Got exceptio

    根据网上搜的解决方案 基本都是说连接的mysql编码不对 改alter database hive character set latin1 但是依然报错 根据后半段报错 MetaException message Got exceptio
  • Linux用dd命令制作启动盘

    1 将U盘格式化成 FAT32 格式 按Ctrl R 打开cmd 输入diskpart 输入list disk select disk 1 输入clean 2 在windows 系统上找到Disk Management 选择disk 1 右
  • linux命令批量修改文件名称

    批量修改文件名称 剔除部分相同的内容 for name in ls a do mv name name x86 64 unknown linux gnu a done 解释说明 ls a 是改目录下所有的 a文件 mv 源文件名 替换文件名
  • Unity学习记录——粒子系统与流动效果

    Unity学习记录 粒子系统与流动效果 前言 本文是中山大学软件工程学院2020级3d游戏编程与设计的最终作业 编程题 粒子光环 1 概述 粒子系统在unity官网与老师课件中的概念定义如下 粒子系统 Unity 手册 一个粒子系统可以模拟