Unity之Fire_HeavySmoke

突然记起来去年领导让我做了个另一个项目中火的Demo。

要求是:首先随着时间火可进行四周漫延。

    然后在燃烧到一定时间后最选燃烧的地方熄灭。

    最后是需要沿着地面燃烧的。

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

public class FireSystem : MonoBehaviour
{
    public float height = 10000;
    ///// <summary>
    ///// 初始火点位置
    ///// </summary>
    //public Vector3 position;
    ///// <summary>
    ///// 大小
    ///// </summary>
    //public float size;
    ///// <summary>
    ///// 火种
    ///// </summary>
    //public GameObject fire;
    ///// <summary>
    ///// 浓烟
    ///// </summary>
    //public GameObject smoke;

    //void Start()
    //{
    //    fire.particleSystem.emissionRate = 1f;
    //    var f1 = Fire.Create(this, Fire.FireLife.Recession);
    //    var f2 = Fire.Create(this, Fire.FireLife.Stable);
    //    var f3 = Fire.Create(this, Fire.FireLife.Grow);
    //    f2.transform.position = f1.transform.position + speed.normalized * size;//----当size改变,size不作为...
    //    f3.transform.position = f2.transform.position + speed.normalized * size;//----size作为目标大小(当size改变过大时模型异常)

    //    f1.transform.localScale = new Vector3(size, 1, size);
    //    f2.transform.localScale = new Vector3(size, 1, size);
    //    f3.transform.localScale = new Vector3(0.001f, 0.001f, 0.001f);
    //    fire.SetActive(false);
    //}
    /// <summary>
    /// 扩散速度
    /// </summary>
    public Vector2 speed;
    public Vector2 size = new Vector2(16, 16);
    Vector2 _speed;
    Vector2 _size;
    float time;

    void Update()
    {
        if (time != 0)
        {
            if (_size == Vector2.zero)
            {
                _size = size;
            }
            else if (_size != size || speed != _speed)
            {
                //var s = (size + _size) / 2;
                int i = 0;
                foreach (Transform item in transform)
                {
                    if (item.gameObject.activeSelf)
                    {
                        FireRegulateSize(item, speed, new Vector2(size.x / _size.x, size.y / _size.y), i);
                        i++;
                    }
                }
                _size = size;
                _speed = speed;
            }

            transform.localRotation = Quaternion.AngleAxis(Vector2.Angle(new Vector2(0, 1), speed), Vector3.up);
            transform.position += new Vector3(speed.x, 0, speed.y) * (Time.time - time);
            foreach (Transform t in transform)
            {
                FireNearFloor(height, t);
            }
        }
        time = Time.time;
    }

    private static void FireRegulateSize(Transform t, Vector3 speed, Vector2 scale, int i)
    {
        t.localScale = new Vector3(t.localScale.x * scale.x, t.localScale.y * scale.y, 1);
        t.localPosition = new Vector3(0, 0, t.localScale.y * i);

        var s = scale.x * scale.y;

        t.particleSystem.emissionRate = t.particleSystem.emissionRate * s;
        t.particleSystem.maxParticles = (int)(t.particleSystem.maxParticles * s);
        foreach (Transform item in t)
        {
            //if (item.name == "HeavySmoke")
            {
                item.particleSystem.emissionRate = item.particleSystem.emissionRate * s;
                item.particleSystem.maxParticles = (int)(item.particleSystem.maxParticles * s);
            }
        }
    }

    private static void FireNearFloor(float height, Transform t)
    {
        RaycastHit hit = default(RaycastHit);

        RaycastHit hitInfo1 = new RaycastHit();
        RaycastHit hitInfo2 = new RaycastHit();

        var b1 = Physics.Raycast(t.position, Vector3.up, out hitInfo1) || Physics.Raycast(t.position + Vector3.up * height, -Vector3.up, out hitInfo1);
        var b2 = Physics.Raycast(t.position, -Vector3.up, out hitInfo2) || Physics.Raycast(t.position - Vector3.up * height, Vector3.up, out hitInfo2);

        if (b1 && !b2)
            hit = hitInfo1;
        else if (!b1 && b2)
            hit = hitInfo2;
        else if (b1 && b2)
        {
            if ((hitInfo1.point - t.position).magnitude < (hitInfo2.point - t.position).magnitude)
                hit = hitInfo1;
            else
                hit = hitInfo2;
        }

        if (hit.transform != null)
        {
            t.position = hit.point;
            for (int i = 0; i < t.childCount; i++)
            {
                if (t.GetChild(i).name == "glow")
                {
                    t.GetChild(i).localRotation = Quaternion.FromToRotation(Vector3.up, hit.normal);
                    break;
                }
            }
        }
    }
}
  1 using UnityEngine;
  2 using System.Collections;
  3 using System.Collections.Generic;
  4 using System.Linq;
  5
  6 public class FireSystem : MonoBehaviour
  7 {
  8     public float height;
  9     ///// <summary>
 10     ///// 初始火点位置
 11     ///// </summary>
 12     //public Vector3 position;
 13     ///// <summary>
 14     ///// 大小
 15     ///// </summary>
 16     //public float size;
 17     ///// <summary>
 18     ///// 火种
 19     ///// </summary>
 20     //public GameObject fire;
 21     ///// <summary>
 22     ///// 浓烟
 23     ///// </summary>
 24     //public GameObject smoke;
 25
 26     //void Start()
 27     //{
 28     //    fire.particleSystem.emissionRate = 1f;
 29     //    var f1 = Fire.Create(this, Fire.FireLife.Recession);
 30     //    var f2 = Fire.Create(this, Fire.FireLife.Stable);
 31     //    var f3 = Fire.Create(this, Fire.FireLife.Grow);
 32     //    f2.transform.position = f1.transform.position + speed.normalized * size;//----当size改变,size不作为...
 33     //    f3.transform.position = f2.transform.position + speed.normalized * size;//----size作为目标大小(当size改变过大时模型异常)
 34
 35     //    f1.transform.localScale = new Vector3(size, 1, size);
 36     //    f2.transform.localScale = new Vector3(size, 1, size);
 37     //    f3.transform.localScale = new Vector3(0.001f, 0.001f, 0.001f);
 38     //    fire.SetActive(false);
 39     //}
 40     /// <summary>
 41     /// 扩散速度
 42     /// </summary>
 43     public Vector3 speed;
 44     public Vector2 Size;
 45     Vector2 _size;
 46     float time;
 47
 48     void Update()
 49     {
 50         if (time != 0)
 51         {
 52             if (_size != Size)
 53             {
 54                 int i = 0;
 55                 foreach (Transform item in transform)
 56                 {
 57                     if (item.gameObject.activeSelf)
 58                     {
 59                         FireRegulateSize(item, Size, i);
 60                         i++;
 61                     }
 62                 }
 63                 _size = Size;
 64             }
 65
 66             transform.position += speed * (Time.time - time);
 67             foreach (Transform t in transform)
 68             {
 69                 FireNearFloor(height, t);
 70             }
 71         }
 72         time = Time.time;
 73     }
 74
 75     private static void FireRegulateSize(Transform t, Vector2 size, int i)
 76     {
 77         t.localScale = new Vector3(size.x, size.y, 1);
 78         t.localPosition = new Vector3(0, -size.x * i * 4, 0);
 79         //foreach (Transform item in t)
 80         {
 81             //item.Translate(new Vector3(-size, 0,0)*Time.deltaTime);//虽平移但改变了原始速度
 82             t.particleSystem.emissionRate = t.particleSystem.emissionRate * Mathf.Sqrt(size.x * size.y);
 83             t.particleSystem.maxParticles = (int)(t.particleSystem.maxParticles * Mathf.Sqrt(size.x * size.y));
 84         }
 85     }
 86
 87     private static void FireNearFloor(float height, Transform t)
 88     {
 89         RaycastHit hit = default(RaycastHit);
 90
 91         RaycastHit hitInfo1 = new RaycastHit();
 92         RaycastHit hitInfo2 = new RaycastHit();
 93
 94         var b1 = Physics.Raycast(t.position, Vector3.up, out hitInfo1) || Physics.Raycast(t.position + Vector3.up * height, -Vector3.up, out hitInfo1);
 95         var b2 = Physics.Raycast(t.position, -Vector3.up, out hitInfo2) || Physics.Raycast(t.position - Vector3.up * height, Vector3.up, out hitInfo2);
 96
 97         if (b1 && !b2)
 98             hit = hitInfo1;
 99         else if (!b1 && b2)
100             hit = hitInfo2;
101         else if (b1 && b2)
102         {
103             if ((hitInfo1.point - t.position).magnitude < (hitInfo2.point - t.position).magnitude)
104                 hit = hitInfo1;
105             else
106                 hit = hitInfo2;
107         }
108
109         if (hit.transform != null)
110         {
111             t.position = hit.point;
112             for (int i = 0; i < t.childCount; i++)
113             {
114                 if (t.GetChild(i).name == "glow")
115                 {
116                     t.GetChild(i).localRotation = Quaternion.FromToRotation(new Vector3(0, 0, 1), hit.normal);
117                     break;
118                 }
119             }
120         }
121     }
122 }
时间: 2024-10-01 03:16:33

Unity之Fire_HeavySmoke的相关文章

Unity 崩溃问题解决方法——之一

友情提示:工作随记,不喜勿喷 注意:文艺青年可以略过,暴力青年欢迎采纳 Library文件夹 Unity每次编译都会生成这个东西,不用担心丢失的问题.所以,干掉他! 选中 + Delete   或者  选中 + Shift  + Delete 网上看了很多方法,就觉得这个简单,粗暴,是我喜欢的类型. 优点:上面说了 缺点:如果工程过大,重新编译时间会比较长.(但是对于查Log日志来说,相对快点)

unity 射线检测

unity中射线检测时非常实用也经常实用的一种手段.下面讲解一下射线检测问题. 1)Ray 根据射线端点和射线的方向定义一条射线 Ray ray= new Ray(transform.position, transform.forward); 定义一个包含射线投射信息的变量RaycastHit hit,并进行射线检测Physics.SphereCast RaycastHit hit; if(Physics.SphereCast(ray,1f,out hit)) { if(hit.distance

关于Unity中的道具拾取(专题六)

原理就是把道具做成触发器,触发器就是当我们有碰撞发生的时候,只会检测碰撞,而不会有任何改变物理运动状态的过程. 触发器非常适合道具拾取,因为它不会改变原本运动物体的任何物理属性,但是依然会检测碰撞,响应物理事件. 道具拾取实例 1.创建Unity项目和文件目录,保存场景 2.导入金币模型资源rc_fx_obj_04_mod.FBX和obj_04_tex.png,设置材质球的shader为Lagacy Shaders---->Diffuse,颜色设置为255,255,255,255 3.创建一个平

关于Unity协程(Coroutine)

协程官方doc解释A coroutine is a function that can suspend its execution(yield) until the given given YieldInstruction finishes. StartCoroutine开启协程 先执行协程中的代码 碰到yield return时控制权交给unity引擎 引擎继续做接下来的工作例如第一次yield return之后执行StartCoroutine下一行代码 直到满足yield指令的要求才会重新进

Unity使用DLL库

Unity3D 能够很方便的集成一些外部插件,以便调用现有的动态链接库.下面会介绍Unity中如何集成Dll的两种方法.1. 标准引用这里所使用的语言是C#. 1.1 新建C#类库项目,这里就不多介绍了. 1.2 项目建好后正常的编写代码 以上是一个简单的测试代码. 1.3 将项目属性 -> 应用程序 -> 目标框架:改为 .NET Framework 3.5或以下 .这一步很重要,因为Unity3D(当前的Unity3D版本是3.5版) 支持的 .Net 是3.5版. 如果选择的是4.0版会

Unity 脚本&lt;1&gt;

RaycastHit2D hit = Physics2D.Linecast(targetPosition, targetPosition + new Vector2(x, y)); 猜测是linecast函数一旦检测到第一个碰撞体之后就会停止检测. 所以把自身检测进去之后就不会检测墙了.估计Physics.Raycast函数也有此性质,这里要注意一下. 2. Unity 2D两种常用判断点击的方法 1.Raycast法 原理相同于3D中得Raycast法,具体使用略有区别. RaycastHit

Unity编辑器扩展chapter1

Unity编辑器扩展chapter1 unity通过提供EditorScript API 的方式为我们提供了方便强大的编辑器扩展途径.学好这一部分可以使我们学会编写一些工具来提高效率,甚至可以自制一些小的插件应用的项目工程中去,达到复用的目的.今天首先创建一个新场景生成的菜单项,生成的场景已经绑定好需要的游戏对象及脚本. Tips:1.官方API 2.编辑器扩展脚本都需放在Editor文件夹下,Editor的层级和数目没有要求 EditorUtil.cs :编辑器扩展类,向外部提供编辑器扩展方法

Unity Update 详解

0x01:简介 Unity的脚本继承了Monobehaviour类,在脚本中定义函数: void FixedUpdate(){} void Update(){} void LateUpdate(){} 脚本如果是激活的,这三个函数会被上层逻辑每帧调用,FixedUpdate调用的次数和fixedTime有关,后面详细介绍,Update和LateUpdate每帧调用一次. 0x02:实现 一般游戏流程都类似下面代码示例: /*************************************

unity 5.3 的 JSON Serialization

孙广东  2015.12.23 JSON 序列化功能和从 JSON 格式 转换到 对象.与 web 服务交互,或只是为了打包和拆包数据 到一个基于文本的格式很容易,这可以非常有用. 使用简单      JSON 序列化功能是围绕一个'structured'的 JSON,意味着你描述变量将要存储在您的 JSON 数据中通过创建一个类或结构的概念.例如: [Serializable] public class MyClass { public int level; public float time