实现原理:雨和雪的实现基本类似,天空中飘的雨和雪,地上的水花和雪花,增加一个下落速度和风速,就形成了天气了。
天气雪实现步骤:
1、预生成Mesh:随机生成多个空中飘落的雪网格和地面上的雪花网格。
2、预生成雪shader和雪花shader,雪shader支持雪的显示,雪花shader支持序列帧动画显示。
3、新建一个雪相机,该相机只渲染Water层,所有和雪有关的都挂到Water层。
4、创建雪模板gameobj,模板包括MeshRenderer、雪shader创建的材质Material、MeshFilter。
5、创建雪花模板gameobj,模板包括MeshRenderer、雪花shader创建的材质Material、MeshFilter。
6、根据模板创建雪群:按高度分为上中下三层,随着时间下落到一定高度最下层会放到最上层,如此循环。
7、帧循环更新:雪相机跟随主相机偏移(xz变y不变),雪根据下落速度变化高度,根据风速变化水平位移,风速随时间变化,雪花随时间变化显示不同的动画关键帧。
8、雪从最高点重新下落会随机更新MeshFilter中mesh网格。
9、关闭雪的时候不是一下全部消失,得有个缓冲过程,都下落到最低点的时候消失。
雪网格:
1 using UnityEngine; 2 using UnityEditor; 3 using System.IO; 4 using System.Collections; 5 6 public class GenSnowMesh 7 { 8 9 public const int numberOfParticles = 60; //雪的粒子数 10 public const float areaSize = 80.0f; //范围 因为雪的下落速度比较慢,所以范围要大一点,防止人物移动太快造成穿帮 11 public const float areaHeight = 15.0f; 12 public const float particleSize = 0.3f; 13 public const float flakeRandom = 0.1f; 14 public const float flakeWidth = 0.15f; 15 public static Vector3 cameraRight = new Vector3(-1, 0, 0); 16 [MenuItem("GameEditor/scene/Weather/Snow/GenMesh")] 17 static public void GenMesh() 18 { 19 for (int i = 0; i < 10; i++) 20 { 21 Mesh m1 = CreateMesh(); 22 AssetDatabase.CreateAsset(m1, "Assets/_Resource/model/prefab/weather/snow/SnowFx/snow_LQ" + i + ".asset"); 23 } 24 } 25 26 public static Mesh CreateMesh() 27 { 28 //Vector3 cameraRight1 = cameraRight * Random.Range(0.1f, 2.0f) + cameraRight * Random.Range(0.1f, 2.0f);// Vector3.forward;//Camera.main.transform.right; 29 //cameraRight1 = Vector3.Normalize(cameraRight1); 30 Vector3 cameraUp = new Vector3(0, 0.7f, 0.7f); 31 Mesh mesh = new Mesh(); 32 int particleNum = numberOfParticles; 33 Vector3[] verts = new Vector3[4 * particleNum]; 34 Vector2[] uvs = new Vector2[4 * particleNum]; 35 36 int[] tris = new int[2 * 3 * particleNum]; 37 38 Vector3 position; 39 for (int i = 0; i < particleNum; i++) 40 { 41 int i4 = i * 4; 42 int i6 = i * 6; 43 44 position.x = areaSize * (Random.value - 0.5f); 45 position.y = areaHeight * Random.value; 46 position.z = areaSize * (Random.value - 0.5f); 47 48 //float rand = Random.value; 49 float widthWithRandom = particleSize + Random.Range(-flakeRandom, flakeRandom); 50 float heightWithRandom = widthWithRandom;//particleSize + rand * flakeRandom; 51 52 verts[i4 + 0] = position - cameraRight * widthWithRandom;// - 0.0 * heightWithRandom; 53 verts[i4 + 1] = position + cameraRight * widthWithRandom;// - 0.0 * heightWithRandom; 54 verts[i4 + 2] = position + cameraRight * widthWithRandom + cameraUp * 2.0f * heightWithRandom; 55 verts[i4 + 3] = position - cameraRight * widthWithRandom + cameraUp * 2.0f * heightWithRandom; 56 57 58 uvs[i4 + 0] = new Vector2(0.0f, 0.0f); 59 uvs[i4 + 1] = new Vector2(1.0f, 0.0f); 60 uvs[i4 + 2] = new Vector2(1.0f, 1.0f); 61 uvs[i4 + 3] = new Vector2(0.0f, 1.0f); 62 63 64 tris[i6 + 0] = i4 + 0; 65 tris[i6 + 1] = i4 + 1; 66 tris[i6 + 2] = i4 + 2; 67 tris[i6 + 3] = i4 + 0; 68 tris[i6 + 4] = i4 + 2; 69 tris[i6 + 5] = i4 + 3; 70 } 71 72 mesh.vertices = verts; 73 mesh.triangles = tris; 74 mesh.uv = uvs; 75 mesh.RecalculateBounds(); 76 77 return mesh; 78 } 79 80 [MenuItem("GameEditor/scene/Weather/Snow/GenSnowLieMesh")] 81 static public void GenSnowlieMesh() 82 { 83 //#if UNITY_EDITOR 84 // if (generateNewAssetsOnStart) { 85 // // create & save 3 meshes 86 for (int i = 0; i < 10; i++) 87 { 88 Mesh m1 = CreateSplashMesh(); 89 AssetDatabase.CreateAsset(m1, "Assets/_Resource/model/prefab/weather/snow/SnowFx/snowlie_LQ" + i+".asset"); 90 } 91 //AssetDatabase.CreateAsset(m2, "Assets/Objects/RainFx/" + gameObject.name + "_LQ1.asset"); 92 //AssetDatabase.CreateAsset(m3, "Assets/Objects/RainFx/" + gameObject.name + "_LQ2.asset"); 93 //Debug.Log ("Created new rain meshes in Assets/Objects/RainFx/"); 94 // } 95 //#endif 96 } 97 98 static private Mesh CreateSplashMesh() 99 { 100 Mesh mesh = new Mesh(); 101 Vector3 cameraRight1 = cameraRight * Random.Range(0.1f, 2.0f) + cameraRight * Random.Range(0.1f, 2.0f);// Vector3.forward;//Camera.main.transform.right; 102 cameraRight1 = Vector3.Normalize(cameraRight1); 103 Vector3 cameraUp = Vector3.Cross(cameraRight1, Vector3.up); 104 cameraUp = Vector3.Normalize(cameraUp); 105 106 //int particleNum = QualityManager.quality > Quality.Medium ? numberOfParticles : numberOfParticles / 2; 107 int particleNum = numberOfParticles; 108 109 Vector3[] verts = new Vector3[4 * particleNum]; 110 Vector2[] uvs = new Vector2[4 * particleNum]; 111 Vector2[] uvs2 = new Vector2[4 * particleNum]; 112 Vector3[] normals = new Vector3[4 * particleNum]; 113 114 int[] tris = new int[2 * 3 * particleNum]; 115 116 Vector3 position; 117 for (int i = 0; i < particleNum; i++) 118 { 119 int i4 = i * 4; 120 int i6 = i * 6; 121 122 position.x = areaSize * (Random.value - 0.5f); 123 position.y = 0.0f; 124 position.z = areaSize * (Random.value - 0.5f); 125 126 float rand = Random.value; 127 float widthWithRandom = flakeWidth + Random.Range(-flakeRandom, flakeRandom); 128 float heightWithRandom = widthWithRandom;//particleSize + rand * flakeRandom; 129 130 verts[i4 + 0] = position - cameraRight1 * widthWithRandom;// - 0.0 * heightWithRandom; 131 verts[i4 + 1] = position + cameraRight1 * widthWithRandom;// - 0.0 * heightWithRandom; 132 verts[i4 + 2] = position + cameraRight1 * widthWithRandom + cameraUp * 2.0f * heightWithRandom; 133 verts[i4 + 3] = position - cameraRight1 * widthWithRandom + cameraUp * 2.0f * heightWithRandom; 134 135 uvs[i4 + 0] = new Vector2(0.0f, 0.0f); 136 uvs[i4 + 1] = new Vector2(1.0f, 0.0f); 137 uvs[i4 + 2] = new Vector2(1.0f, 1.0f); 138 uvs[i4 + 3] = new Vector2(0.0f, 1.0f); 139 140 Vector2 tc1 = new Vector2(Random.Range(0.0f, 1.0f), Random.Range(0.0f, 1.0f)); 141 uvs2[i4 + 0] = new Vector2(tc1.x, tc1.y); 142 uvs2[i4 + 1] = new Vector2(tc1.x, tc1.y); 143 uvs2[i4 + 2] = new Vector2(tc1.x, tc1.y); 144 uvs2[i4 + 3] = new Vector2(tc1.x, tc1.y); 145 146 tris[i6 + 0] = i4 + 0; 147 tris[i6 + 1] = i4 + 1; 148 tris[i6 + 2] = i4 + 2; 149 tris[i6 + 3] = i4 + 0; 150 tris[i6 + 4] = i4 + 2; 151 tris[i6 + 5] = i4 + 3; 152 } 153 154 mesh.vertices = verts; 155 mesh.triangles = tris; 156 mesh.uv = uvs; 157 mesh.uv2 = uvs2; 158 mesh.RecalculateBounds(); 159 return mesh; 160 } 161 }