欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

UGUI--自定义重写Button

程序员文章站 2022-05-30 17:36:59
...

重写UGUI的Btn组件有其自身的局限性,所以重写了UGUI的Btn,满足 《AFK Wizard》游戏开发中的需求,

效果图:
UGUI--自定义重写Button

上代码:
Scripts:

using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using System.Collections.Generic;

namespace H2Engine {

    public class H2BtnHelper : MonoBehaviour, IPointerDownHandler, IPointerUpHandler, IPointerExitHandler, IPointerEnterHandler 
    {
        #region 按钮事件
        private UnityEvent PointerDownEvent;

        private UnityEvent PointerUpEvent;

        private UnityEvent PointerEnterEvent;

        private UnityEvent PointerExitEvent;

        private UnityEvent PointerClickEvent;

        private UnityEvent PointerLongPressEvent;

        private bool isInTransformArea = true;

        [HideInInspector]
        public bool LongPressInstall = false;

        [HideInInspector]
        public float pressTime = 0;

        private float pressTimer = 0;

        private bool stratPress = false;

        public void OnPointerDown(PointerEventData eventData)
        {
            if (PointerDownEvent != null)
            {
                PointerDownEvent?.Invoke();
            }
            if (LongPressInstall)
            {
                stratPress = true;
                pressTimer = 0;
            }
            switch (TweenType)
            {
                case BtnTweenType.None:
                    break;
                case BtnTweenType.Scale:
                    SetBtnNormToScaling();
                    break;
                case BtnTweenType.Darken:
                    if (isGrayed == false)
                    {
                        SetBtnNormToDarken();
                    }
                    break;
                default:
                    break;
            }
            if (soundID != 0)
            {
                Debug.LogError("处理音效逻辑");
            }
        }

        public void OnPointerUp(PointerEventData eventData)
        {
            if (PointerUpEvent != null)
            {
                PointerUpEvent?.Invoke();
            }
            if (PointerClickEvent != null)
            {
                //移动端
                if (Application.isMobilePlatform)
                {
                    PointerClickEvent?.Invoke();
                }
                //PC
                else
                {
                    if (isInTransformArea)
                    {
                        PointerClickEvent?.Invoke();
                    }
                }
            }
            if (LongPressInstall == true && stratPress == true)
            {
                stratPress = false;
            }
            switch (TweenType)
            {
                case BtnTweenType.None:
                    break;
                case BtnTweenType.Scale:
                    SetBtnScalingToNormal();
                    break;
                case BtnTweenType.Darken:
                    if (isGrayed == false)
                    {
                        SetBtnDarkenToNormal();
                    }
                    break;
                default:
                    break;
            }
        }

        public void OnPointerEnter(PointerEventData eventData)
        {
            isInTransformArea = true;
            if (PointerEnterEvent != null)
            {
                PointerEnterEvent?.Invoke();
            }
        }

        public void OnPointerExit(PointerEventData eventData)
        {
            isInTransformArea = false;
            if (PointerExitEvent != null)
            {
                PointerExitEvent?.Invoke();
            }
            if (LongPressInstall && stratPress)
            {
                stratPress = false;
            }
        }

        /// <summary>
        /// 按下
        /// </summary>
        public UnityEvent onDown
        {
            get
            {
                if (PointerDownEvent == null)
                {
                    PointerDownEvent = new UnityEvent();
                }
                return PointerDownEvent;
            }
        }

        /// <summary>
        /// 抬起
        /// </summary>
        public UnityEvent onUp
        {
            get
            {
                if (PointerUpEvent == null)
                {
                    PointerUpEvent = new UnityEvent();
                }
                return PointerUpEvent;
            }
        }

        /// <summary>
        /// 进入
        /// </summary>
        public UnityEvent onEnter
        {
            get
            {
                if (PointerEnterEvent == null)
                {
                    PointerEnterEvent = new UnityEvent();
                }
                return PointerEnterEvent;
            }
        }

        /// <summary>
        /// 离开
        /// </summary>
        public UnityEvent onExit
        {
            get
            {
                if (PointerExitEvent == null)
                {
                    PointerExitEvent = new UnityEvent();
                }
                return PointerExitEvent;
            }
        }

        /// <summary>
        /// 点击
        /// </summary>
        public UnityEvent onClick
        {
            get
            {
                if (PointerClickEvent == null)
                {
                    PointerClickEvent = new UnityEvent();
                }
                return PointerClickEvent;
            }
        }

        /// <summary>
        /// 长按
        /// </summary>
        public UnityEvent onLongPress
        {
            get
            {
                if (PointerLongPressEvent == null)
                {
                    PointerLongPressEvent = new UnityEvent();
                }
                return PointerLongPressEvent;
            }
        }


        void Update()
        {
            if (LongPressInstall && stratPress)
            {
                pressTimer += Time.deltaTime;
                if (pressTimer >= pressTime)
                {
                    pressTimer = 0;
                    stratPress = false;
                    PointerLongPressEvent?.Invoke();
                }
            }
        }
        #endregion

        #region 按钮灰化

        [HideInInspector]
        public bool GrayedInstall = false;

        [HideInInspector]
        public bool isGrayed = false;        
        public bool IsGrayed {
            get {
                return isGrayed;
            }
            set {
                isGrayed = value;
                if (isGrayed)
                {
                    SetBtnNormalToGrayed();
                }
                else
                {
                    SetBtnGrayedToNormal();
                }
            }
        }

        [HideInInspector]
        public Color textGrayedColor = Color.grey;

        private Material greadyedShader;

        private List<GrayedTextColor> GrayedTextList;

        private List<Image> GrayedImageList;

        public void SetBtnNormalToGrayed()
        {
            if (GrayedTextList == null || GrayedImageList == null)
            {
                GrayedTextList = new List<GrayedTextColor>();
                GrayedImageList = new List<Image>();
                GetAllNeedGrayedComp(gameObject);
            }
            for (int i = 0; i < GrayedTextList.Count; i++)
            {
                GrayedTextList[i].SetGradyed();
            }
            for (int i = 0; i < GrayedImageList.Count; i++)
            {
                if (greadyedShader == null)
                {
                    greadyedShader = new Material(Shader.Find("GreyShader"));
                }
                GrayedImageList[i].material = greadyedShader;
            }
        }

        public void SetBtnGrayedToNormal()
        {
            if (GrayedTextList == null || GrayedImageList == null)
            {
                GrayedTextList = new List<GrayedTextColor>();
                GrayedImageList = new List<Image>();
                GetAllNeedGrayedComp(gameObject);
            }
            for (int i = 0; i < GrayedTextList.Count; i++)
            {
                GrayedTextList[i].SetNormal();
            }
            for (int i = 0; i < GrayedImageList.Count; i++)
            {
                GrayedImageList[i].material = null;
            }

            if (Application.isPlaying == false)
            {
                ClearBtnColorData();
            }
        }

        public void ClearBtnColorData()
        {
            GrayedTextList = null;
            GrayedImageList = null;
        }

        private void GetAllNeedGrayedComp(GameObject gameObject)
        {
            Text text = gameObject.transform.GetComponent<Text>();
            if (text)
            {
                GrayedTextColor textColor = new GrayedTextColor(text,text.color,textGrayedColor);
                GrayedTextList.Add(textColor);
            }
            Image image = gameObject.transform.GetComponent<Image>();
            if (image)
            {
                GrayedImageList.Add(image);
            }
            if (gameObject.transform.childCount < 1)
            {
                return;
            }
            for (int i = 0; i < gameObject.transform.childCount; i++)
            {
                var obj = gameObject.transform.GetChild(i).gameObject;
                GetAllNeedGrayedComp(obj);
            }
        }

        
       

        #endregion

        #region 按钮音效
        [HideInInspector]
        public bool SoundInstall = false;

        [HideInInspector]
        public int soundID = 0;

        [HideInInspector]
        public int soundVolume = 0;
        #endregion

        #region 按钮动效
        [HideInInspector]
        public bool TweenInstall = false;

        [HideInInspector]
        public BtnTweenType TweenType = BtnTweenType.None;

        [HideInInspector]
        public float scaleSize = 1; 

        [HideInInspector]
        public Color PressColor = Color.gray;

        private List<DarkenImageColor> DarkenImageList;

        private void GetAllNeedDarkenComps(GameObject gameObject)
        {
            Image image = gameObject.transform.GetComponent<Image>();
            if (image)
            {
                DarkenImageList.Add(new DarkenImageColor(image, PressColor));
            }
            if (gameObject.transform.childCount < 1)
            {
                return;
            }
            for (int i = 0; i < gameObject.transform.childCount; i++)
            {
                var obj = gameObject.transform.GetChild(i).gameObject;
                GetAllNeedDarkenComps(obj);
            }
        }

        private void SetBtnNormToDarken()
        {
            if (DarkenImageList == null)
            {
                DarkenImageList = new List<DarkenImageColor>();
                GetAllNeedDarkenComps(gameObject);
            }
            for (int i = 0; i < DarkenImageList.Count; i++)
            {
                DarkenImageList[i].SetDarken();
            }
        }

        private void SetBtnDarkenToNormal()
        {
            if (DarkenImageList == null)
            {
                DarkenImageList = new List<DarkenImageColor>();
                GetAllNeedDarkenComps(gameObject);
            }
            for (int i = 0; i < DarkenImageList.Count; i++)
            {
                DarkenImageList[i].SetNormal();
            }
        }

        private void SetBtnNormToScaling()
        {
            transform.localScale = new Vector3(transform.localScale.x * scaleSize, transform.localScale.y * scaleSize, transform.localScale.z * scaleSize);
        }

        private void SetBtnScalingToNormal()
        {
            transform.localScale = new Vector3(transform.localScale.x / scaleSize, transform.localScale.y / scaleSize, transform.localScale.z / scaleSize);
        }
        #endregion
    }
}



```csharp

namespace H2Engine {
    /// <summary>
    /// 按钮类型
    /// </summary>
    public enum BtnType
    {
        //正常
        Normal,
        //单选
        SingleChoice,
        //复选
        Multiple           
    }

    /// <summary>
    /// 按钮动画类型
    /// </summary>
    public enum BtnTweenType
    {
        //无
        None,
        //缩放
        Scale,
        //变暗
        Darken,
    }
}



using UnityEngine;
using UnityEngine.UI;


namespace H2Engine{
    public class DarkenImageColor
    {
        private Image Image;

        private Color NormalColor;

        private Color DarkenColor;
        public DarkenImageColor(Image image, Color darkenColor)
        {
            Image = image;
            NormalColor = image.color;
            DarkenColor = darkenColor;
        }

        /// <summary>
        /// 设置正常
        /// </summary>
        public void SetNormal()
        {
            Image.color = NormalColor;
        }

        /// <summary>
        /// 设置变暗
        /// </summary>
        public void SetDarken()
        {
            Image.color = DarkenColor;
        }
    }
}

using UnityEngine;
using UnityEngine.UI;

namespace H2Engine {
    public class GrayedTextColor
    {
        public Text Text { get; set; }

        public Color NormalColor { get; set; }

        public Color GrayedColor { get; set; }

        public GrayedTextColor(Text text, Color normalColor, Color grayedColor)
        {
            Text = text;
            NormalColor = normalColor;
            GrayedColor = grayedColor;
        }

        public void SetGradyed()
        {
            Text.color = GrayedColor;
        }

        public void SetNormal()
        {
            Text.color = NormalColor;
        }
    }
}

Editor:

using UnityEngine;
using H2Engine;
using UnityEditor;

[CustomEditor(typeof(H2BtnHelper))]
public class H2BtnHelperEditor : Editor
{

    H2BtnHelper h2BtnHelper;

    public override void OnInspectorGUI()
    {
        if (h2BtnHelper == null)
        {
            h2BtnHelper = target as H2BtnHelper;
        }

        #region 长按
        EditorGUILayout.HelpBox("长按设置", MessageType.None);
        h2BtnHelper.LongPressInstall = EditorGUILayout.Toggle("LongPressInstall", h2BtnHelper.LongPressInstall);
        if (h2BtnHelper.LongPressInstall)
        {
            h2BtnHelper.pressTime = EditorGUILayout.Slider("PressTime", h2BtnHelper.pressTime, 0, 10);
        }
        else
        {
            h2BtnHelper.pressTime = 0;
        }
        EditorGUILayout.Space();
        #endregion

        #region 灰化
        EditorGUILayout.HelpBox("灰化设置", MessageType.None);
        h2BtnHelper.GrayedInstall = EditorGUILayout.Foldout(h2BtnHelper.GrayedInstall, "GrayedInstall");
        if (h2BtnHelper.GrayedInstall)
        {
            h2BtnHelper.textGrayedColor = EditorGUILayout.ColorField("TextGrayedColor", h2BtnHelper.textGrayedColor);
            h2BtnHelper.isGrayed = EditorGUILayout.Toggle("IsGrayed", h2BtnHelper.isGrayed);
            if (h2BtnHelper.isGrayed)
            {
                h2BtnHelper.SetBtnNormalToGrayed();
            }
            else
            {
                h2BtnHelper.SetBtnGrayedToNormal();
            }
            if (GUILayout.Button("默认设置"))
            {
                h2BtnHelper.SetBtnGrayedToNormal();
                h2BtnHelper.textGrayedColor = Color.grey;
                h2BtnHelper.isGrayed = false;
            }
        }
        EditorGUILayout.Space();
        #endregion

        #region 音效
        EditorGUILayout.HelpBox("音效设置", MessageType.None);
        h2BtnHelper.SoundInstall = EditorGUILayout.Foldout(h2BtnHelper.SoundInstall, "SoundInstall");
        if (h2BtnHelper.SoundInstall)
        {
            h2BtnHelper.soundID = EditorGUILayout.IntField("Audio ID", h2BtnHelper.soundID);
            if (h2BtnHelper.soundVolume < 0)
            {
                h2BtnHelper.soundVolume = 0;
            }
            if (h2BtnHelper.soundVolume > 100)
            {
                h2BtnHelper.soundVolume = 100;
            }
            h2BtnHelper.soundVolume = EditorGUILayout.IntField("Audio Volume", h2BtnHelper.soundVolume);
        }

        EditorGUILayout.Space();
        #endregion

        #region 动效
        EditorGUILayout.HelpBox("动效设置", MessageType.None);
        h2BtnHelper.TweenInstall = EditorGUILayout.Foldout(h2BtnHelper.TweenInstall, "TweenInstall");
        if (h2BtnHelper.TweenInstall)
        {
            h2BtnHelper.TweenType = (BtnTweenType)EditorGUILayout.EnumPopup("TweenType", h2BtnHelper.TweenType);
            switch (h2BtnHelper.TweenType)
            {
                case BtnTweenType.None:

                    break;
                case BtnTweenType.Scale:
                    if (h2BtnHelper.scaleSize < 0.1)
                    {
                        h2BtnHelper.scaleSize = 0.1f;
                    }
                    if (h2BtnHelper.scaleSize > 1)
                    {
                        h2BtnHelper.scaleSize = 1;
                    }
                    h2BtnHelper.scaleSize = EditorGUILayout.FloatField("Scale Size", h2BtnHelper.scaleSize);
                    break;
                case BtnTweenType.Darken:
                    h2BtnHelper.PressColor = EditorGUILayout.ColorField("Darken Color", h2BtnHelper.PressColor);
                    if (GUILayout.Button("默认设置"))
                    {
                        h2BtnHelper.PressColor = Color.gray;
                    }
                    break;
                default:
                    break;
            }
        } 
        #endregion
        

        base.OnInspectorGUI();
    }
}

Shader:

Shader "GreyShader"
{
    Properties
    {
        [PerRendererData] _MainTex("Sprite Texture", 2D) = "white" {}
        _Color("Tint", Color) = (1,1,1,1)
    }

        SubShader
        {
            Tags
        {
            "Queue" = "Transparent"
            "IgnoreProjector" = "True"
            "RenderType" = "Transparent"
            "PreviewType" = "Plane"
            "CanUseSpriteAtlas" = "True"
        }
            // 源rgba*源a + 背景rgba*(1-源A值)   
            Blend SrcAlpha OneMinusSrcAlpha

            Pass
        {
            CGPROGRAM
    #pragma vertex vert     
    #pragma fragment frag     
    #include "UnityCG.cginc"     

            struct appdata_t
        {
            float4 vertex   : POSITION;
            float4 color    : COLOR;
            float2 texcoord : TEXCOORD0;
        };

        struct v2f
        {
            float4 vertex   : SV_POSITION;
            fixed4 color : COLOR;
            half2 texcoord  : TEXCOORD0;
        };

        sampler2D _MainTex;
        fixed4 _Color;

        v2f vert(appdata_t IN)
        {
            v2f OUT;
            OUT.vertex = UnityObjectToClipPos(IN.vertex);
            OUT.texcoord = IN.texcoord;
    #ifdef UNITY_HALF_TEXEL_OFFSET     
            OUT.vertex.xy -= (_ScreenParams.zw - 1.0);
    #endif     
            OUT.color = IN.color * _Color;
            return OUT;
        }

        fixed4 frag(v2f IN) : SV_Target
        {
            half4 color = tex2D(_MainTex, IN.texcoord) * IN.color;
            float grey = dot(color.rgb, fixed3(0.22, 0.707, 0.071));
            return half4(grey,grey,grey,color.a);
        }
            ENDCG
        }
        }
}

相关标签: UGUI