Unity-3D 粒子光圈效果

这一次要完成的是http://i-remember.fr/en 网站所示的白色圆圈效果。

首先,我们先来看一下它的效果:

一、网站效果展示

二、创建粒子

设置相关参数

把相机背景色调黑

三、编写脚本

1、新建脚本:ParticleRotate.cs,并将其拖到Paticle System中。

2、创建粒子数组,初始化。同时我们需要为记录每个粒子的初始角度,初始半径。考虑后续可能每个粒子会有更多属性,所以写了一个class来管理粒子属性

根据下图我们知道,需要随机生成角度以及半径,从而表示出某一个粒子的特定位置。

    //创建粒子系统,粒子数组,粒子数目,声明粒子环的半径
    public ParticleSystem particleSystem;
    private ParticleSystem.Particle[] particlesArray;
    private particleClass[] particleAttr; //粒子属性数组
    public int particleNum = 10000;

    public class particleClass {
        public float radiu = 0.0f;
        public float angle = 0.0f;
        public particleClass(float radiu_, float angle_)
        {
            radiu = radiu_;
            angle = angle_;
        }
    }
    void Start()
    {
        particlesArray = new ParticleSystem.Particle[particleNum];
        particleSystem.maxParticles = particleNum;
        particleSystem.Emit(particleNum);
        particleSystem.GetParticles(particlesArray);
        for (int i = 0; i < particleNum; i++)
        {//相应初始化操作,为每个粒子设置半径,角度
        }
        //设置粒子
        particleSystem.SetParticles(particlesArray, particleNum);
    }

3、先考虑在最大半径为maxRadius 最小半径为minRadius的区间内随机为每个粒子生成半径

    float randomAngle = Random.Range(0.0f, 360.0f);
    float randomRadius = Random.Range(minRadius, maxRadius);
    particleAttr[i] = new particleClass(randomRadius, randomAngle);
    particlesArray[i].position = new Vector3(randomRadius * Mathf.Cos(randomAngle), randomRadius * Mathf.Sin(randomAngle), 0.0f);

效果如下:

4、OK接下来要让它动起来~~那么问题来了~怎么动。

我的想法是,把这一堆粒子分成两Part,第一部分顺时针转,第二部分逆时针转。只要在update函数里面更改它的角度就好了。

    public int Part = 2;
    void Update()
    {
        //设置为两部分的粒子,一部分顺时针,一部分逆时针。
        for (int i = 0; i < particleNum; i++)
        {
            if (i % 2 == 0)  particleAttr[i].angle += (i % Part + 1) * speed;
            else particleAttr[i].angle -= (i % Part + 1) * speed;

            particleAttr[i].angle = particleAttr[i].angle % 360;
            float rad = particleAttr[i].angle / 180 * Mathf.PI;
            particlesArray[i].position = new Vector3(particleAttr[i].radiu * Mathf.Cos(rad), particleAttr[i].radiu * Mathf.Sin(rad), 0f);
        }
        particleSystem.SetParticles(particlesArray, particleNum);
    }

动起来的效果:

5、好吧不得不承认动起来的效果太奇怪了。仔细研究一下就会发现。产生的半径必须是要在[minRadius, maxRadius]区间的没错,但是同时也要更为集中在中间的某一块区域,这样才能实现网站的效果。

这也是我觉得的最有趣的地方。

首先想到的解决方式:正态分布。

不过只有python有相应的正态分布的库。利用c#写一个正态分布太麻烦了。

然后我就找到了box-muller

传送门: http://baike.baidu.com/view/1710258.htm

方法如下:

如果在 (0,1] 值域内有两个独立的随机数字 U1 和 U2,

可以使用以下两个等式中的任一个算出一个正态分布的随机数字 Z:

Z = R * cos( θ )或Z = R * sin( θ )

其中,R = sqrt(-2 * ln(U2)) && θ = 2 * π * U1

正态值 Z 有一个等于 0 的平均值和一个等于 1 的标准偏差,可使用以下等式将 Z 映射到一个平均值为 m、标准偏差为 sd 的统计量 X:X = m + (Z * sd)

然后将该方法写入for循环中。

            // 一种待完善的产生随机粒子的办法 box-muller
            float sita = 2 * Mathf.PI * Random.Range(0, 1);
            float R = Mathf.Sqrt(-2 * Mathf.Log(Random.Range(0, 1)));
            float Z = R * Mathf.Cos(sita);
            float randomRadius = (minRadius + maxRadius) / 2 + Z * 2.5f;
            //print(randomRadius);
            Debug.Log("r = " + R);
            Debug.Log(randomRadius);

什么问题呢? R求出来是无限,等着把Log里面的数值改为0.7,

运行慢不说。10000个粒子unity跑了接近一分钟才运行出来。吓得我以为炸了。

而且效果十分糟糕。

好吧~我无能为力。然后就看了大神这一块实现的代码。

            // 随机产生每个粒子距离中心的半径,同时粒子要集中在平均半径附近
            float midRadius = (maxRadius + minRadius) / 2;
            float minRate = Random.Range(1.0f, midRadius / minRadius);
            float maxRate = Random.Range(midRadius / maxRadius, 1.0f);
            float randomRadius = Random.Range(minRadius * minRate, maxRadius * maxRate);

非常巧妙地利用了三个随机函数,实现粒子的集中。

相当于[ [minRadius, midRadius] , [midRadius, maxRadius] ] 这样的区间中产生随机数。自然靠中间的随机数也会更加集中。

真是神奇。

6、那把这部分代码添加到我的代码中之后。实现的效果就很不错啦。

至此实验完成:

下面是完整的代码:

using UnityEngine;
using System.Collections;

public class ParticleRotate : MonoBehaviour
{
    public class particleClass
    {
        public float radiu = 0.0f;
        public float angle = 0.0f;
        public particleClass(float radiu_, float angle_)
        {
            radiu = radiu_;
            angle = angle_;
        }
    }

    //创建粒子系统,粒子数组,粒子数目,声明粒子环的半径
    public ParticleSystem particleSystem;
    private ParticleSystem.Particle[] particlesArray;
    private particleClass[] particleAttr; //粒子属性数组
    public int particleNum = 10000;
    public float minRadius = 5.0f;
    public float maxRadius = 10.0f;
    public int Part = 2;
    public float speed = 0.1f;

    void Start()
    {
        particleAttr = new particleClass[particleNum];
        particlesArray = new ParticleSystem.Particle[particleNum];
        particleSystem.maxParticles = particleNum;
        particleSystem.Emit(particleNum);
        particleSystem.GetParticles(particlesArray);
        for (int i = 0; i < particleNum; i++)
        {   //相应初始化操作,为每个粒子设置半径,角度
            //产生一个随机角度
            float randomAngle = Random.Range(0.0f, 360.0f);

            // 随机产生每个粒子距离中心的半径,同时粒子要集中在平均半径附近
            float midRadius = (maxRadius + minRadius) / 2;
            float minRate = Random.Range(1.0f, midRadius / minRadius);
            float maxRate = Random.Range(midRadius / maxRadius, 1.0f);
            float randomRadius = Random.Range(minRadius * minRate, maxRadius * maxRate);

            ////一种待完善的产生随机粒子的办法 box-muller
            //float sita = 2 * Mathf.PI * Random.Range(0, 1);
            //float R = Mathf.Sqrt(-2 * Mathf.Log(0.7f));
            //float Z = R * Mathf.Cos(sita);
            //float randomRadius = (minRadius + maxRadius) / 2 + Z * 2.5f;
            //print(randomRadius);
            //Debug.Log("r = " + R);
            //Debug.Log(randomRadius);

            //粒子属性设置
            particleAttr[i] = new particleClass(randomRadius, randomAngle);
            particlesArray[i].position = new Vector3(randomRadius * Mathf.Cos(randomAngle), randomRadius * Mathf.Sin(randomAngle), 0.0f);
        }
        //设置粒子
        particleSystem.SetParticles(particlesArray, particleNum);
    }

    void Update()
    {
        //设置为两部分的粒子,一部分顺时针,一部分逆时针。
        for (int i = 0; i < particleNum; i++)
        {
            if (i % 2 == 0) particleAttr[i].angle += (i % Part + 1) * speed;
            else particleAttr[i].angle -= (i % Part + 1) * speed;

            //根据新的角度重新设置位置
            particleAttr[i].angle = particleAttr[i].angle % 360;
            float rad = particleAttr[i].angle / 180 * Mathf.PI;
            particlesArray[i].position = new Vector3(particleAttr[i].radiu * Mathf.Cos(rad), particleAttr[i].radiu * Mathf.Sin(rad), 0f);
        }
        particleSystem.SetParticles(particlesArray, particleNum);
    }
}
时间: 2024-10-08 14:18:48

Unity-3D 粒子光圈效果的相关文章

Unity 3D Game 粒子光环

介绍 参考 http://i-remember.fr/en 制作类似该网站效果 基本步骤 创建粒子光环(空对象) 将摄像机背景置为黑色 创建粒子系统,配置参数 新建 C# 脚本,命名为 ParticleRing ParticleRing.cs 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686

【Unity 3D】学习笔记四十二:粒子特效

粒子特效 粒子特效的原理是将若干粒子无规则的组合在一起,来模拟火焰,爆炸,水滴,雾气等效果.要使用粒子特效首先要创建,在hierarchy视图中点击create--particle system即可 粒子发射器 粒子发射器是用于设定粒子的发射属性,比如说粒子的大小,数量和速度等.在创建完粒子对象后,在右侧inspector视图中便可以看到所有的粒子属性: emit:是否是使用粒子发射器. min size:粒子最小尺寸. max size:粒子最大尺寸. min energy:粒子的最小生命周期

关于Unity中粒子效果的使用

粒子效果1: 游戏中会有很炫酷的特效,比如爆炸,水花,火焰等;2: unity提供粒子编辑器,方便特效人员来开发很炫酷的特效;3.粒子效果一般有专门的粒子特效师来做,我们只需要拿来用就好了,很多参数没必要掌握. Particle System组件面板 1: 粒子系统主体;2: 喷射(Emission);3: 形态(shape);4: 生命周期内的速度偏移(velocity over lifetime);5: 生命周期内的限制速度(limit velocity over lifetime);6:

【Unity 3D】学习笔记三十四:游戏元素——常用编辑器组件

常用编辑器组件 unity的特色之一就是编辑器可视化,很多常用的功能都可以在编辑器中完成.常用的编辑器可分为两种:原有组件和拓展组件.原有组件是编辑器原生的一些功能,拓展组件是编辑器智商通过脚本拓展的新功能. 摄像机 摄像机是unity最为核心组件之一,游戏界面中显示的一切内容都得需要摄像机来照射才能显示.摄像机组件的参数如下: clear flags:背景显示内容,默认的是skybox.前提是必须在render settings 中设置天空盒子材质. background:背景显示颜色,如果没

【Unity 3D】学习笔记三十二:游戏元素——游戏光源

游戏光源 在3D游戏中,光源是一个非常具有特色的游戏组件.用来提升游戏画面质感的.如果没有加入光源,游戏场景可能就会显得很昏暗.在unity中提供了三种不同的光源类型:点光源,聚光灯,平行光. 点光源 顾名思义,点光源是从一个点向周围散发出光的光源,就像电灯一样.创建点光源在hierarchy视图中点击create--point light: 创建完以后,点击点光源对象,在右侧inspector视图中可以看到点光源的所有信息: type:光源的类型.有point(点光源),directional

【Unity 3D】学习笔记四十五:游戏实例——击垮围墙

用这个游戏实例来总结之前我们复习的所有关于物理引擎的知识.在游戏中,发送一个球形的炮弹来击垮前面的墙.给炮弹与墙都添加了刚体组件,给炮弹绑定了粒子系统,并且在炮弹的粒子动画中添加了5组不同的颜色,显示移动轨迹. using UnityEngine; using System.Collections; public class Script_06_14 : MonoBehaviour { //炮弹对象 private GameObject obj; //准心贴图 public Texture te

Unity 实现物体破碎效果(转)

感谢网友分享,原文地址(How to Make an Object Shatter Into Smaller Fragments in Unity),中文翻译地址(Unity实现物体破碎效果) In this tutorial I will show you how to create a simple shattering effect for your Unity game. Instead of just "deleting" a crate (or any other obje

Unity 3d中Shader是什么,可以吃吗?

众所周知,Unity3d是一款跨平台非常广的游戏引擎,上手容易,界面友好,集成功能众多,是目前开发手游的主流引擎.本人有幸使用Unity 3d进行开发已一年多时间,已领略了这歀引擎的强大之处. 编写shader也是我工作内容的一部分,先来说说shader是什么吧,我以自己的理解说明一下: 首先 shader是一种语言,一种在GPU,也就是显卡上执行的高级语言.shader的本意是着色器,可以自定义GPU的渲染管线中的两个环节(即顶点和片段).由此,我们可以控制对象在屏幕上的渲染效果,甚至实现一些

【Unity 3D】学习笔记三十七:物理引擎——碰撞与休眠

碰撞与休眠 上一篇笔记说过,当给予游戏对象刚体这个组件以后,那么这个组件将存在碰撞的可能性.一旦刚体开始运动,那么系统方法便会监视刚体的碰撞状态.一般刚体的碰撞分为三种:进入碰撞,碰撞中,和碰撞结束.关于休眠可以理解成为让游戏对象变成静止状态.如果给某个游戏对象休眠的状态,那么这个物体将立马静止,不再运动. 碰撞 首先学习下碰撞几个重要的方法: OnCollisionEnter(  ):刚体开始接触的时候,立即调用. OnCollisionStay(  ):碰撞过程中,每帧都会调用此方法,直到撞