由于不会使用Step和Clip方法,所以使用了更消耗性能的if**else**
下面为自己实现的Shader
Shader "MyShader/MyLifeBarGap"
{
Properties
{
[HideInInspector]
_Width("每100血的宽度", float) = 10
_Color("血条颜色", Color) = (1,1,1,1)
_BlackWidth("分隔线宽度", float) = 1
_BloodVolume("总血量(会X1000)", float) = 5
_BlackColor("间隔颜色", Color) = (0,0,0,1)
_life("剩余生命百分比", Range(0,1)) = 1
_LossColor("损失血量颜色", Color) = (1,1,1,1)
}
SubShader
{
Cull Off
ZWrite Off
ZTest Off
Blend SrcAlpha OneMinusSrcAlpha
Tags
{
"Queue" = "Transparent"
"RenderType" = "Transparent"
}
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
float _Width;
fixed4 _Color;
float _BlackWidth;
float _BloodVolume;
fixed4 _BlackColor;
fixed _life;
fixed4 _LossColor;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
fixed4 frag (v2f i) : SV_Target
{
half virtualHealthBarWidth = i.uv.x * 100 * _BloodVolume;
//如果当前位置是1000血的倍数,且在间隔的两倍宽度位置,设置颜色显示为黑色
if (virtualHealthBarWidth % _Width > _Width - _BlackWidth * 2 && (virtualHealthBarWidth + _Width) / _Width % _Width < 1)
{
return _BlackColor;
}
//如果当前位置在间隔宽度内
else if (virtualHealthBarWidth % _Width > _Width - _BlackWidth)
{
//设置一半显示为黑色
if (i.uv.y > 0.4)
{
return _BlackColor;
}
else
{
//如果未超出剩余血量,显示为血条颜色,否则显示为损失的颜色
if(i.uv.x < _life)
return _Color;
else
return _LossColor;
}
}
//剩余情况为不在间隔范围内
else
{
//如果未超出剩余血量,显示为血条颜色,否则显示为损失的颜色
if (i.uv.x < _life)
return _Color;
else
return _LossColor;
}
}
ENDCG
}
}
}
下面为使用了Step和clip方法的Shader,其他人写的,然后我多加了一个pass,来设置血条颜色和损失血量颜色
Shader "Unlit/LifeBarGap"
{
Properties
{
PerSplitWidth("分割快宽度", float) = 10
GapLineWidth("分割线宽度", float) = 3
[HideInInspector]
BlackColor("BlackColor", Color) = (0,0,0,1)
UVFactor("UV缩放系数", float) = 1
UVStart("UV起始点", float) = 0
_Color("血条颜色", Color) = (1,1,1,1)
_LossColor("损失血量颜色", Color) = (1,1,1,1)
_life("剩余生命百分比", Range(0,1)) = 1
}
SubShader
{
Cull Off
Zwrite Off
ZTest Off
Blend SrcAlpha OneMinusSrcAlpha
Tags
{
"Queue" = "Transparent"
"RenderType" = "Transparent"
}
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
fixed4 _Color;
fixed _life;
fixed4 _LossColor;
v2f vert(appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
fixed4 frag(v2f i) : SV_Target
{
if (i.uv.x < _life)
return _Color;
else
return _LossColor;
}
ENDCG
}
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
float PerSplitWidth;
float GapLineWidth;
half4 BlackColor;
float UVFactor;
float UVStart;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
fixed4 frag (v2f i) : SV_Target
{
half virtualHealthBarWidth = (i.uv.x - UVStart) * 100 * UVFactor;
half result = step(PerSplitWidth - GapLineWidth, virtualHealthBarWidth % PerSplitWidth);
half bigGapResult = step((virtualHealthBarWidth + PerSplitWidth) / PerSplitWidth % 10, 1);
half secondResult = step(PerSplitWidth - GapLineWidth * 2,
virtualHealthBarWidth % PerSplitWidth) * bigGapResult;
//return half4(secondResult,0,0,1);
// call discard
// if ZWrite is Off, clip() is fast enough on mobile, because it won't write the DepthBuffer, so no GPU pipeline stall(confirmed by ARM staff).
// 以每100生命值作为间隔
clip((result + secondResult - 1) + (i.uv.y - 0.4 + bigGapResult * 0.4));
return BlackColor;
}
ENDCG
}
}
}