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 }