zoukankan      html  css  js  c++  java
  • 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);
            }
        }
    }
  • 相关阅读:
    【Spring注解驱动开发】二狗子让我给他讲讲@EnableAspectJAutoProxy注解
    【Spring注解驱动开发】你敢信?面试官竟然让我现场搭建一个AOP测试环境!
    【Nginx】如何基于主从模式搭建Nginx+Keepalived双机热备环境?这是最全的一篇了!!
    华为分析+App Linking:一站式解决拉新、留存、促活难
    deeplink跳转快应用返回出现两次系统添加桌面的弹框
    4月26日19:30,#HMS Core Insights#直播系列第二期来了!
    HMS Toolkit自动化环境配置,助您高效集成HMS Core
    全体注意!一大波鸿蒙三方库即将到来
    HMS Toolkit助力开发者高效集成HMS Core
    教你使用一套代码解决出海问题
  • 原文地址:https://www.cnblogs.com/joeshifu/p/5489859.html
Copyright © 2011-2022 走看看