最近需要一个3D的圆形血条功能,多方测试完成后做个简单总结。
1、上来的思路考虑NGUI实现的Fill效果,查看NGUI代码发现它的实现方式是动态修改Mesh形状实现的,所以考虑按本方案尝试一次。
动态创建圆形Mesh功能代码参考:http://blog.csdn.net/ecidevilin/article/details/52456107
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混合,方案三不使用贴图,但是圆环如果要圆润的话,模型面数较高。具体情况自己衡量考虑。