UGUI--自定义重写Button
程序员文章站
2022-05-30 17:36:59
...
重写UGUI的Btn组件有其自身的局限性,所以重写了UGUI的Btn,满足 《AFK Wizard》游戏开发中的需求,
效果图:
上代码:
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
}
}
}
推荐阅读
-
Android自定义Button并设置不同背景图片的方法
-
WPF自定义控件和样式之自定义按钮(Button)
-
在ASP.NET 2.0中操作数据之四十五:DataList和Repeater里的自定义Button
-
WPF自定义控件和样式之自定义按钮(Button)
-
在ASP.NET 2.0中操作数据之四十五:DataList和Repeater里的自定义Button
-
Android中的Button自定义点击效果实例代码
-
iOS自定义button抖动效果并实现右上角删除按钮
-
Android自定义格式显示Button的布局思路
-
Jquery自定义button按钮的几种方法
-
Android中的Button自定义点击效果实例代码