unity学习笔记—一部分粒子系统

每一个粒子系统都会包含一个主要模块(main Module),该模块不能被禁用或删除。
Start life time :表示粒子初始的生命周期
Start speed : 表示粒子的初始速度,可以设定在一个区间范围内
Start size: 表示粒子的初始大小,可以设定在一个区间范围内
start rotation:表示粒子的初始方向,可以设定在一个区间范围内
Start color:表示粒子的初始颜色,可以设定在两个颜色之间随机产生
Max particles:表示粒子最大的数量,过多粒子会影响游戏性能

Emission模块:它的Rate表示单位时间内抛出的粒子数量
Shape模块: shape属性表示抛射物的形状,有angle和radius属性具体控制。Emit from表示从哪里发射粒子,比如base就是从底部发射粒子
Force over LifeTime模块:生命周期内的作用力控制,可以设定X,Y,Z轴上受力的大小。
Color over LifeTime模块: 可以编辑粒子在其生命周期内的颜色变化。
Size over LifeTime:模块 控制粒子生命周期内大小的变化,有在两个值之间变化,或者是一条曲线形式的变化,或者介于两条曲线之间的变化
Rotation by Speed模块:由速度控制旋转
Renderer 模块:可以设置粒子渲染的方式,比如可以设定粒子朝向摄像机进行渲染。

接下来,这个官方实例使用了以上几个特性完成了火焰烟雾粒子效果,并完成了一个由鼠标控制移动的洒水粒子效果并且做了粒子碰撞事件检测并实现了,当粒子与桶盖发生碰撞的时候,桶盖会有力的效果,与火焰粒子效果碰撞的时候,会减弱火焰粒子效果与灯光强度。

当粒子与场景中的碰撞体发生碰撞的时候,会触发粒子碰撞事件,这时候可以在加入回调函数OnParticleCollision中加入碰撞处理代码。
触发碰撞事件的消息会发给粒子系统的组件对象和与粒子系统发生碰撞的物体。若OnParticleCollision是在与粒子发生碰撞的碰撞体所属的游戏对象上绑定的脚本中执行的,则OnParticleCollision中的参数other表示粒子系统,若OnParticleCollision是绑定在粒子对象上面的脚本,则参数other就是表示与粒子对象发生碰撞的碰撞体所绑定的游戏对象。都可以使用ParticleSystem.getCollisionEvent来获得碰撞事件数组对象。

这个是控制火焰烟雾粒子的脚本

using System.Collections;
[System.Serializable]
public class ParticleHelper{

    public ParticleSystem part;         //粒子系统组件对象
    public Light light;                 //点光源对象



    public bool varyAlpha;              // 表示是否改变ParticleSystem组件的startColor属性的alpha值
    public float minAlpha;              //表示alpha的最小值
    public float maxAlpha;              //表示alpha的最大值 
    public float alphaIncreaseRate;     //alpha增大的量
    public float alphaDecreseRate;      //alpha减小的量
    public float alphaVariation;        //表示用随机函数生成alpha值增大时的边界值


    public bool varyEmission;              // 表示是否改变ParticleSystem组件的emission属性的emssion值
    public float minEmission;              //表示emission的最小值
    public float maxEmission;              //表示emission的最大值 
    public float emissionIncreaseRate;     //emission增大的量
    public float emissionDecreseRate;      //emission减小的量
    public float emissionVariation;        //表示用随机函数生成emission值增大时的边界值


    public bool varyIntensity;              // 表示是否改变light组件的intensity属性的值
    public float minIntensity;              //表示intensity的最小值
    public float maxIntensity;              //表示intensity的最大值 
    public float intensityIncreaseRate;     //intensity增大的量
    public float intensityDecreseRate;      //intensity减小的量
    public float intensityVariation;        //表示用随机函数生成intensity值增大时的边界值

    public bool varyRange;                   // 表示是否改变light组件的range属性的值
    public float minRange;                   //表示range的最小值
    public float maxRange;                  //表示range的最大值 
    public float rangeIncreaseRate;        //range增大的量
    public float rangeDecreseRate;        //range减小的量
    public float rangeVariation;          //表示用随机函数生成range值增大时的边界值

    public void IcreaseRange()
    {

        if (light.range < maxRange) {
            float range = light.range;
            range += rangeIncreaseRate * Time.deltaTime;
            range += Random.Range (0f, rangeVariation);
            light.range = range;
        }
    }
    public void DcreaseRange()
    {
        if (light.range > minRange)
            light.range -= rangeDecreseRate * Time.deltaTime;

    }



    public void IcreaseIntensity()
    {
        if (light.intensity < maxIntensity) {
            float intensity = light.intensity;
            intensity += intensityIncreaseRate * Time.deltaTime;
            intensity += Random.Range (0f, intensityVariation);
            light.intensity = intensity;
        }
    }
    public void DcreaseIntensity()
    {
        if (light.intensity > minIntensity)
            light.intensity -= intensityDecreseRate * Time.deltaTime;
    }

    public void IcreaseEmission()
    {        //增加粒子系统排放物的随机性
        if (part.emissionRate < maxEmission) {
            float emissionRate = part.emissionRate;
            emissionRate += emissionIncreaseRate * Time.deltaTime;
            emissionRate += Random.Range (0f, emissionVariation);
            part.emissionRate = emissionRate;
        }

    }
    public void DecreaseEmission()
    {
        if (part.emissionRate > minEmission)
            part.emissionRate -= emissionDecreseRate * Time.deltaTime;
    }

    public void IcreaseAlpha()
    {
         //如果粒子系统的startcolor的alpha值小于最大值,让它先按alphaIncreaseAlpha的速度进行变化,然后加上一个区间里的值,这样可以增强粒子系统的随机性
        if (part.startColor.a < maxAlpha) {      
            Color adjustedColour = part.startColor;
            adjustedColour.a += alphaIncreaseRate *Time.deltaTime;
            adjustedColour.a += Random.Range (0f, alphaVariation);
            part.startColor = adjustedColour;
        }

    }

    public void DecreaseAlpha()
    {   //用于处理水滴与火焰粒子的的碰撞事件
        if (part.startColor.a > minAlpha) {
            Color adjustedColour = part.startColor;
            adjustedColour.a -= alphaDecreseRate * Time.deltaTime;
            part.startColor = adjustedColour;
        }

    }



}

因为一个汽油桶上有多个烟雾火光脚本,所以用一个脚本来统一控制几个粒子效果

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class Fire : MonoBehaviour {


    public List<ParticleHelper> particles;

    void Update () {

        foreach (ParticleHelper ph in particles) {
            if (ph.varyAlpha)
                ph.IcreaseAlpha ();
            if (ph.varyEmission)
                ph.IcreaseEmission ();
            if (ph.varyIntensity)
                ph.IcreaseIntensity ();
            if (ph.varyRange)
                ph.IcreaseRange ();
        }

    }
}

这个是控制洒水器的脚本

using UnityEngine;
using System.Collections;

public class sprinkler : MonoBehaviour {

    private float heightAboveFloor;
    private ParticleSystem[] sprinklers;      //定义一个保存粒子系统的数组,因为脚本绑定对象有多个粒子系统


    private ParticleCollisionEvent[][] collisionEvents;//碰撞事件数组,因为有多个粒子系统所以是一个交错数组(因为每个粒子系统碰撞情况不同)
    private GameObject barrel;     //火焰粒子系统的父对象
    private Fire fire;            //控制火焰效果的脚本

    void OnParticleCollision(GameObject other)
    {
        if (other.tag == "FireBarrel") {
            for (int i = 0; i < collisionEvents.Length; i++)
                collisionEvents [i] = new ParticleCollisionEvent[sprinklers [i].GetSafeCollisionEventSize ()];
            for (int i = 0; i < collisionEvents.Length; i++)
                sprinklers [i].GetCollisionEvents (gameObject, collisionEvents [i]);
            for (int i = 0; i < collisionEvents.Length; i++) {
                for (int j = 0; j < collisionEvents [i].Length; j++) {       
                    foreach(ParticleHelper ph in fire.particles)
                    {
                        if (ph.varyAlpha)
                            ph.DecreaseAlpha ();
                        if (ph.varyEmission)
                            ph.DecreaseEmission ();
                        if (ph.varyIntensity)
                            ph.DcreaseIntensity ();
                        if (ph.varyRange)
                            ph.DcreaseRange ();

                    }

                }
            }
        }
    }
    void Awake()
    {     //获得子物体的粒子系统
        sprinklers = GetComponentsInChildren<ParticleSystem>();

    }
    void Start()
    {    collisionEvents = new ParticleCollisionEvent[sprinklers.Length][];
        barrel = GameObject.FindWithTag ("FireBarrel");
        fire = barrel.GetComponent<Fire> ();
        heightAboveFloor = transform.position.y;
    }
    void Update () {
        //点击鼠标左键
        if (Input.GetMouseButton (0)) {
            //放回一条从摄像机发出且通过鼠标点击点的射线
            Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);
            RaycastHit[] hit;
            //返回射线接触到的碰撞列表
            hit = Physics.RaycastAll (ray);
            foreach (RaycastHit h in hit) {
                //如果碰撞体是地面
                if (h.collider.name == "ground") {
                    //将洒水器对象移动到地面上方的位置
                    transform.position = h.point + new Vector3 (0f, heightAboveFloor, 0f);
                }
            }
            //开启粒子效果
            if (!sprinklers [0].isPlaying) {
                for (int i = 0; i < sprinklers.Length; i++) {
                    sprinklers [i].Play ();
                }
            }


        } else {
            //如果鼠标左键没有点击事件则终止粒子效果的播放
            if (sprinklers [0].isPlaying) {
                for (int i = 0; i < sprinklers.Length; i++)
                    sprinklers[i].Stop();
            }
        }
}
}

控制桶盖受力的脚本,还是绑定在粒子系统上的

using System.Collections;

public class BarrelLid : MonoBehaviour {

    public float dropletForce;                           //表示水滴与桶盖之间力的大小
    public Rigidbody lid;                                //表示桶盖对象
    private ParticleSystem[] sprinklers;                 //与桶盖进行碰撞的粒子系统列表
    private ParticleCollisionEvent[][] collisionEvents;  //表示粒子碰撞时间的数组对象,这里使用的不是二维数组,而是交错数组


    void OnParticleCollision(GameObject other)
    {
        if (collisionEvents == null)
            return;
        //如果粒子系统碰撞的物体是桶盖
        if (other.tag == "Barrel") {
            //首先确定每个粒子系统返回了多少在安全范围内与桶盖的碰撞对象,并给每个粒子系统对应的数组创建数组实体
            for (int i = 0; i < collisionEvents.Length; i++)
                collisionEvents [i] = new ParticleCollisionEvent[sprinklers [i].GetSafeCollisionEventSize ()];
            for (int k = 0; k < collisionEvents.Length; k++)
                sprinklers [k].GetCollisionEvents (gameObject, collisionEvents [k]);

            for (int i2 = 0; i2 < collisionEvents.Length; i2++) {          
                for (int j = 0; j < collisionEvents [i2].Length - 1; j++) {
                    //在每个粒子碰撞时间的位置,施加一个力
                    lid.AddForceAtPosition (Vector3.down * dropletForce, collisionEvents [i2] [j].intersection);
                }
            }


        }
    }
    void Awake()
    {

        sprinklers = GetComponentsInChildren<ParticleSystem>();

    }

    void Start () {

        //由游戏对象持有的粒子系统来创建保存每个粒子系统的数组
        collisionEvents = new ParticleCollisionEvent[sprinklers.Length][];
    }

    void Update () {

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值