unity實現3D圓形血條功能
阿新 • • 發佈:2019-02-14
最近需要一個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混合,方案三不使用貼圖,但是圓環如果要圓潤的話,模型面數較高。具體情況自己衡量考慮。