Shader实例:NGUI制作网格样式血条
效果:
思路:
1.算出正确的uv去采样过滤图,上一篇文章说的很明白了。Shader实例:NGUI图集中的UISprite正确使用Shader的方法
2.用当前血量占总血量的百分比来设置shader中的变量,来控制血条的裁剪。
实际操作中,在shader中声明一个uniform float _Factor
然后在C#脚本中,对这个变量进行设置,结果发现,界面上不能实时响应这个值,进行正确的裁剪。
那么我只好牺牲color的一个分量,比如设置g分量,shader中用g分量的值来对血条进行裁剪。最终勉强达到效果。
如果有的其他好的方式,请留言告诉我哦!
shader代码:改写自Unlit – Transparent Colored
//–add– 部分就是我添加的。
Shader "Custom/Unlit/Transparent Colored Hp Mask" { Properties { _MainTex ("Base (RGB), Alpha (A)", 2D) = "black" {} //---add--------------------------------- _MaskTex ("Mask Alpha (A)", 2D) = "white" {} _WidthRate ("Sprite.width/Atlas.width", float) = 1 _HeightRate ("Sprite.height/Atlas.height", float) = 1 _XOffset("offsetX/Atlas.width", float) = 0 _YOffset("offsetY/Atlas.height", float) = 0 //_Factor("factor",range(0,1)) = 1 //-------------------------------------- } SubShader { LOD 100 Tags { "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" } Cull Off Lighting Off ZWrite Off Fog { Mode Off } Offset -1, -1 Blend SrcAlpha OneMinusSrcAlpha Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata_t { float4 vertex : POSITION; float2 texcoord : TEXCOORD0; fixed4 color : COLOR; }; struct v2f { float4 vertex : SV_POSITION; half2 texcoord : TEXCOORD0; fixed4 color : COLOR; }; sampler2D _MainTex; float4 _MainTex_ST; //---add------- sampler2D _MaskTex; float _WidthRate; float _HeightRate; float _XOffset; float _YOffset; //float _Factor; //-------------- v2f vert (appdata_t v) { v2f o; o.vertex = mul(UNITY_MATRIX_MVP, v.vertex); o.texcoord = v.texcoord; o.color = v.color; return o; } fixed4 frag (v2f i) : COLOR { fixed4 col; col = tex2D(_MainTex, i.texcoord); //---------add--------------------------------- //过滤 if(i.color.r<=0.1) { float2 final_uv = float2((i.texcoord.x - _XOffset) / _WidthRate, (i.texcoord.y - _YOffset) / _HeightRate); float curr = final_uv.x; final_uv.x *= 20; col.a = col.a * tex2D(_MaskTex, final_uv).a; if (curr >= i.color.g) { col.a = 0; } /*if (curr >= _Factor) { col.a = 0; }*/ } //----------------------------------------------- return col; } ENDCG } } SubShader { LOD 100 Tags { "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" } Pass { Cull Off Lighting Off ZWrite Off Fog { Mode Off } Offset -1, -1 ColorMask RGB AlphaTest Greater .01 Blend SrcAlpha OneMinusSrcAlpha ColorMaterial AmbientAndDiffuse SetTexture [_MainTex] { Combine Texture * Primary } } } }
C#脚本:挂在UISprite上
using UnityEngine; using System.Collections; public class ScaleTexcoord : MonoBehaviour { private float widthRate; private float heightRate; private float xOffsetRate; private float yOffsetRate; private UISprite sprite; float curr; void Awake() { sprite = GetComponent<UISprite>(); widthRate = sprite.GetAtlasSprite().width * 1.0f / sprite.atlas.spriteMaterial.mainTexture.width; heightRate = sprite.GetAtlasSprite().height * 1.0f / sprite.atlas.spriteMaterial.mainTexture.height; xOffsetRate = sprite.GetAtlasSprite().x * 1.0f / sprite.atlas.spriteMaterial.mainTexture.width; yOffsetRate = (sprite.atlas.spriteMaterial.mainTexture.height-(sprite.GetAtlasSprite().y + sprite.GetAtlasSprite().height)) * 1.0f / sprite.atlas.spriteMaterial.mainTexture.height; } private void Start() { sprite.atlas.spriteMaterial.SetFloat("_WidthRate", widthRate); sprite.atlas.spriteMaterial.SetFloat("_HeightRate", heightRate); sprite.atlas.spriteMaterial.SetFloat("_XOffset", xOffsetRate); sprite.atlas.spriteMaterial.SetFloat("_YOffset", yOffsetRate); } void OnGUI() { if (GUI.Button(new Rect(100, 100, 100, 50), "加")) { curr += 0.1f; sprite.color = new Color(0,curr,1); } if (GUI.Button(new Rect(220, 100, 100, 50), "减")) { curr -= 0.1f; sprite.color = new Color(0, curr, 1); } } }
===================================================================
补充:
上面的方法太复杂了,而且不精准。
后来发现了更好的方式。
效果:
还是使用NGUI的UISlider,改值还是改value。
把血条的UISprite设置成如下,用来平铺。
然后根据比例是设置血条UIsprite的width,
然后再根据比例设置血条UISprite的Scale.x
测试代码:HpBarScript
using UnityEngine; using System.Collections; public class HpBarScript : MonoBehaviour { public UISprite m_hpSprite; public UISlider m_hpSlider; public UISprite m_bgSprite; public float m_bgWidth{get;set;} public float m_hpWidth{get;set;} void Start () { this.m_bgWidth = this.m_bgSprite.width; this.m_hpWidth = this.m_hpSprite.width; } public void SetHpSpriteWidthAndScale(float _width,float _scale) { this.m_hpSprite.width = (int)_width; this.m_hpSprite.transform.localScale = new Vector3(_scale,1,1); } public void SetHpBarSliderValue(float _value) { this.m_hpSlider.value = _value; } }
测试代码:TestHpBar
using UnityEngine; using System.Collections; public class TestHpBar : MonoBehaviour { public HpBarScript m_hpBarScript; public float m_defaultMaxHp = 100; public float m_currMaxHp; private float m_rate; private float m_currHp; void Start () { this.m_currMaxHp=m_defaultMaxHp; this.m_currHp = this.m_currMaxHp; this.m_rate = this.m_defaultMaxHp / m_hpBarScript.m_hpWidth; } void OnGUI() { if(GUI.Button(new Rect(100,100,100,50),"最大血量加10")) { this.m_currMaxHp += 10; float scale = m_defaultMaxHp/this.m_currMaxHp; this.m_hpBarScript.SetHpSpriteWidthAndScale(this.m_currMaxHp/this.m_rate,scale); } if(GUI.RepeatButton(new Rect(100,200,100,50),"加")) { this.m_currHp+=1; this.m_currHp = this.m_currHp>this.m_currMaxHp?this.m_currMaxHp:this.m_currHp; float progress = this.m_currHp/this.m_currMaxHp; this.m_hpBarScript.SetHpBarSliderValue(progress); } if(GUI.RepeatButton(new Rect(100,300,100,50),"减")) { this.m_currHp-=1; this.m_currHp = this.m_currHp<0?0:this.m_currHp; this.m_currHp= Mathf.Min(this.m_currHp,this.m_currMaxHp); float progress = this.m_currHp/this.m_currMaxHp; this.m_hpBarScript.SetHpBarSliderValue(progress); } } }
- 本文固定链接: http://www.shihuanjue.com/?p=315
- 转载请注明: 乔 2016年01月27日 于 是幻觉 发表