1. 程式人生 > >unity實現3D圓形血條功能

unity實現3D圓形血條功能

最近需要一個3D的圓形血條功能,多方測試完成後做個簡單總結。

1、上來的思路考慮NGUI實現的Fill效果,檢視NGUI程式碼發現它的實現方式是動態修改Mesh形狀實現的,所以考慮按本方案嘗試一次。

shader選擇用簡單的混合:

float4 frag(VertexOutput i) : COLOR 
{
	float4 _MainTex_Color = tex2D(_MainTex,TRANSFORM_TEX(i.uv0, _MainTex));
	fixed4 finalRGBA = fixed4(_TintColor.rgb*_MainTex_Color.rgb,_MainTex_Color.a);
      	return finalRGBA;
}

效果圖                                                                                                                                      貼圖

                                                  

2.實現後,考慮血條沒有底色顯示,同時再加一層護盾效果。如果繼續按照方案一來的話,需要建立一個底層的圓形,護盾的圓形,會造成效能損耗,批次過多,所以考慮方案二,依靠shader來實現此功能,模型使用Quad即可。


shader程式碼:

Shader "Example/HpAndHuDun_Tex" 
{
	//屬性
    	Properties 
	{
		_RampTex ("RampTex", 2D) = "white" {}
        	_HpTex ("HpTex", 2D) = "white" {}
		_HpColor ("HpColor", Color) = (0,1,0.006896496,1)
        	_BottomColor ("BottomColor", Color) = (0.5215687,0.5215687,0.5215687,1)        
        	_HpSlider ("HpSlider", Range(0, 1)) = 0.4866171
        	_HuDunTex ("HuDunTex", 2D) = "white" {}
        	_HuDunSlider ("HuDunSlider", Range(0, 1)) = 0.324226
    	}

    	SubShader 
	{
        	Tags 
		{
            		"IgnoreProjector"="True"
            		"Queue"="Transparent"
            		"RenderType"="Transparent"
        	}

        	LOD 100

        	Pass 
		{
            		Name "FORWARD"
            		Tags { "LightMode"="ForwardBase" }
            		Blend SrcAlpha OneMinusSrcAlpha
            		ZWrite Off

            		CGPROGRAM
            		#pragma vertex vert
            		#pragma fragment frag
            		#define UNITY_PASS_FORWARDBASE
            		#include "UnityCG.cginc"
            		#pragma multi_compile_fwdbase
            		#pragma target 3.0

            		uniform sampler2D _HpTex; uniform float4 _HpTex_ST;
            		uniform float4 _BottomColor;
            		uniform float4 _HpColor;
            		uniform float _HpSlider;
            		uniform sampler2D _RampTex; uniform float4 _RampTex_ST;
            		uniform sampler2D _HuDunTex; uniform float4 _HuDunTex_ST;
            		uniform float _HuDunSlider;

			//輸入結構
            		struct VertexInput 
			{
                		float4 vertex : POSITION;
                		float2 texcoord0 : TEXCOORD0;
            		};

			//輸出結構
            		struct VertexOutput 
			{
                		float4 pos : SV_POSITION;
                		float2 uv0 : TEXCOORD0;
            		};

			//頂點計算
            		VertexOutput vert (VertexInput v) 
			{
                		VertexOutput o = (VertexOutput)0;
                		o.uv0 = v.texcoord0;
                		o.pos = mul(UNITY_MATRIX_MVP, v.vertex );
                		return o;
            		}

			//片段計算
            		float4 frag(VertexOutput i) : COLOR 
			{
				//計算hp圈的uv 顏色值
                		float2 hpUV = ((i.uv0*1.1)+(-0.05));
                		float4 _HpTexColor = tex2D(_HpTex,TRANSFORM_TEX(hpUV, _HpTex));

				//漸變圖的顏色值
                		float4 _RampTexColor = tex2D(_RampTex,TRANSFORM_TEX(i.uv0, _RampTex));

				//護盾顏色
                		float2 huDunUV = ((i.uv0*0.9)+0.05);
                		float4 _HuDunTexColor = tex2D(_HuDunTex,TRANSFORM_TEX(huDunUV, _HuDunTex));

				//最後hp顏色
				float3 finalHpColor = lerp( (_HpColor.rgb*_HpTexColor.rgb), (_HpTexColor.rgb*_BottomColor.rgb), trunc((_RampTexColor.r+(1.0-_HpSlider))));

				//最終顏色 混合 護盾和 hp顏色
                		float3 finalColor = (finalHpColor*_HpTexColor.a)+(_HuDunTexColor.rgb*_HuDunTexColor.a);
				float finalAlpha = _HpTexColor.a+(_HuDunTexColor.a*(1.0-trunc((_RampTexColor.r+(1.0-_HuDunSlider)))));

                		return fixed4(finalColor,finalAlpha);
            		}
            		ENDCG
        	}
    }

    FallBack "Diffuse"
}

效果圖如下噪點圖片

                                     

3. 方案二有個問題,因為用了漸變貼圖和trunc方法,在邊緣處有噪點,向朋友諮詢提出如下方案方案二用了alpha,效能一般,考慮進一步優化。使用3D模型 + 顏色來進行處理,UV水平向展開即可。


shader關鍵程式碼:

float4 frag(VertexOutput i) : COLOR
{
	//這步是為了省去if判斷是否在範圍,用擴大10000倍來處理浮點數的精度問題
	float colorSelect = saturate(saturate(i.uv0.x - _Progress) * 10000.0);
	float3 finalColor = _CircleColor.rgb * (1 - colorSelect) + _BackgroundColor.rgb * colorSelect;
	return fixed4(finalColor,1.0);
}

效果圖


最終總結,方案二,模型面數少,用了兩張貼圖和alpha混合,方案三不使用貼圖,但是圓環如果要圓潤的話,模型面數較高。具體情況自己衡量考慮。