我们不使用Fog,通过Sprite 使用定制的shader 来实现上面的效果。
这个Shader主要做的事情:
在Sprite的底部叠加天空的颜色,看起来像渐渐消失。叠加的颜色强度依赖于距离相机的距离,离相机越远,则越强。
Shader如下:
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' Shader "Custom/2DFogSpriteShader" { Properties { [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {} _SkyColor ("Sky Color", Color) = (1,1,1,1) _MaxCamDist("Max Camera distance", float) = 100 [MaterialToggle] PixelSnap ("Pixel snap", Float) = 0 } SubShader { Blend SrcAlpha OneMinusSrcAlpha Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma multi_compile DUMMY PIXELSNAP_ON #include "UnityCG.cginc" struct appdata_t { float4 vertex : POSITION; float4 color : COLOR; float2 texcoord : TEXCOORD0; }; struct v2f { float4 vertex : SV_POSITION; fixed4 color : COLOR; half2 texcoord : TEXCOORD0; float4 worldPos : TEXCOORD1; }; v2f vert(appdata_t IN) { v2f OUT; OUT.vertex = UnityObjectToClipPos(IN.vertex); OUT.texcoord = IN.texcoord; OUT.color = IN.color; OUT.worldPos = mul(unity_ObjectToWorld, IN.vertex); #ifdef PIXELSNAP_ON OUT.vertex = UnityPixelSnap (OUT.vertex); #endif return OUT; } sampler2D _MainTex; fixed4 _SkyColor; float _MaxCamDist; fixed4 frag(v2f IN) : COLOR { float dist = distance(IN.worldPos, _WorldSpaceCameraPos); half4 texcol = tex2D (_MainTex, IN.texcoord) * IN.color; float distFactor = saturate(dist/_MaxCamDist); half4 intercol = lerp(texcol, _SkyColor, distFactor); float gradientFactor = distFactor / 3; half4 finalCol = lerp(_SkyColor, intercol, (IN.texcoord.y - gradientFactor)/ (1 - gradientFactor)) * step(gradientFactor, IN.texcoord.y); if (IN.texcoord.y < gradientFactor) finalCol = _SkyColor; finalCol.a = texcol.a; return finalCol; } ENDCG } } Fallback "Sprites/Default" }
场景中创建若干个Sprite,并将上面的shader创建Material 赋给这些Sprite.
创建 SkyColorManager.cs ,把脚本挂在Camera上。将Camera设置为Solid Color ,通过脚本来设置Camera 背景颜色。
- 通过Gradient 设置颜色渐变,
- 通过 fogMat.SetColor("_SkyColor", Camera.main.backgroundColor); 将背景颜色传给上面的Shader.
- 通过gradient.Evaluate(Mathf.PingPong(timeCounter, 1)); 使背景颜色动态变化。
public class SkyColorManager : MonoBehaviour { private Color skyColor; private Material fogMat; public Gradient gradient; public GameObject boxSprite; private float timeCounter = 0; void Start() { fogMat = boxSprite.GetComponent<Renderer>().sharedMaterial; } void Update () { // timeCounter += Time.deltaTime*0.1f; timeCounter += Time.deltaTime*0.5f; Camera.main.backgroundColor = gradient.Evaluate(Mathf.PingPong(timeCounter, 1)); fogMat.SetColor("_SkyColor", Camera.main.backgroundColor); } }
最后给这些Sprite添加一些上下移动效果,创建SpriteAnim.cs , 并讲他挂到创建的Sprite 上。
public class SpriteAnim : MonoBehaviour { private float maxPosY; private Vector3 mInitPos; private float mTimeCounter = 0; // Use this for initialization void Start () { mInitPos = this.transform.position; maxPosY = Random.Range(1, 2.0f); } // Update is called once per frame void Update () { // mTimeCounter += Time.deltaTime * 0.5f; mTimeCounter += Time.deltaTime * 1.0f; this.transform.position = mInitPos + Vector3.up * (Mathf.PingPong(mTimeCounter,maxPosY)-maxPosY/2.0f); } }
最终效果如下。
Kapture 2019-07-17 at 22.13.13.gif
Unity完整工程源码:请搜索微信公众号UnityAsk,或者 加QQ群:891555732 获取