unity实现3D圆形血条功能

博客介绍了在Unity中实现3D圆形血条和护盾功能的方法。首先尝试通过动态修改Mesh和简单的混合Shader实现,然后为解决性能和批次问题,利用Shader在Quad模型上实现血条和护盾效果。在优化过程中,遇到边缘噪点问题,最后提出了使用3D模型结合颜色处理的方案,权衡模型面数和效果。

最近需要一个3D的圆形血条功能,多方测试完成后做个简单总结。


1、上来的思路考虑NGUI实现的Fill效果,查看NGUI代码发现它的实现方式是动态修改Mesh形状实现的,所以考虑按本方案尝试一次。

动态创建圆形Mesh功能代码参考:http://blog.youkuaiyun.com/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混合,方案三不使用贴图,但是圆环如果要圆润的话,模型面数较高。具体情况自己衡量考虑。



评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值