1.本文内容概述 对于原版本的Button添加按钮缩放比较困难的问题,开发了一个基于dotween的缩放按钮统一插件功能。
主要解决的痛点
Button使用Animation实现各种效果,动画必须要求各个按钮节点相同。
Button的效果比较重量级,对程序来说不好维护
Button不是很灵活,一般游戏工程的按钮比较简单和统一,不需要如此庞大复制的配置以上几点我开发了一个ScaleButton做完UGUI的补充插件。而且可以不断的按照此方法拓展新的功能。分析下UGUI-Button的一些源码,点击效果如何实现的效果的细节。添加一个拓展实现缩放功能(DoTween插件实现的),并且增加一个ScaleButton的编辑器脚本和一个快捷创建按钮的页签。
Button的效果主要是Selectable类的DoStateTransition(SelectionState state, bool instant)方法控制状态的切换。
Selectable.cs 1 2 3 4 5 6 7 8 protected enum SelectionState{ Normal, Highlighted, Pressed, Selected, Disabled }
我们只要实现这个方法,对应状态做对应的变化就行。
3.如何实现点击动画效果 使用doTween会让我们的工作变得简单。这里使用dotween的插件来做一个简单的缩放功能。
基于上面的分析我们创建UIScaleButton,重写DoStateTransition方法。
注意在OnDestroy时对Dotween进行删除
UIScaleButton.cs 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 using System.Collections;using System.Collections.Generic;using UnityEngine;using UnityEngine.EventSystems;using UnityEngine.UI;using DG.Tweening;using Unity.VisualScripting;namespace Rainbow.UI { public class UIScaleButton : Button { [SerializeField ] public float m_ScaleUp = 1f ; [SerializeField ] public float m_ScaleDown = 0.95f ; [SerializeField ] Transform m_Target; private float transScale = 1f ; Tween tween; protected override void DoStateTransition (SelectionState state, bool instant ) { base .DoStateTransition(state, instant); switch (state) { case SelectionState.Normal: transScale = m_ScaleUp; break ; case SelectionState.Pressed: transScale = m_ScaleDown; break ; default : transScale = m_ScaleUp; break ; } DoScale(); } void DoScale () { Transform tweenTrans = m_Target ? m_Target : transform; tween = tweenTrans.DOScale(Vector3.one * transScale, 0.3f ).SetEase(Ease.OutBack); } protected override void OnDestroy () { base .OnDestroy(); tween.Kill(); } } }
另外为UIScaleButton添加一个编辑器脚本。
UIScaleButtonEditor.cs 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 using UnityEditor;using UnityEditor.UI;using UnityEngine;namespace Rainbow.UI { [CustomEditor(typeof(UIScaleButton)) ] [DisallowMultipleComponent ] public class UIScaleButtonEditor : ButtonEditor { SerializedProperty m_ScaleUpProperty; SerializedProperty m_ScaleDownProperty; SerializedProperty m_TargetProperty; protected override void OnEnable () { base .OnEnable(); m_ScaleUpProperty = serializedObject.FindProperty("m_ScaleUp" ); m_ScaleDownProperty = serializedObject.FindProperty("m_ScaleDown" ); m_TargetProperty = serializedObject.FindProperty("m_Target" ); } public override void OnInspectorGUI () { base .OnInspectorGUI(); serializedObject.Update(); EditorGUILayout.PropertyField(m_ScaleUpProperty); EditorGUILayout.PropertyField(m_ScaleDownProperty); EditorGUILayout.PropertyField(m_TargetProperty); serializedObject.ApplyModifiedProperties(); } } }
添加一个快捷创建UIScaleButton的选项。
UGUIExt_CreateObjectMenu.cs 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 using TMPro.EditorUtilities;using UnityEditor;using UnityEngine;using UnityEngine.UI;namespace Rainbow.UI { public static class UGUIExt_CreateObjectMenu { [MenuItem("GameObject/UI/ScaleButton - TextMeshPro" , false, 2031) ] public static void AddButton (MenuCommand menuCommand ) { TMPro_CreateObjectMenu.AddButton(menuCommand); for (int i = 0 ; i < Selection.gameObjects.Length; i++) { string selectName = Selection.gameObjects[i].name; if (selectName == "Button" ) { GameObject tg = Selection.gameObjects[i]; tg.name = "UIScaleButton" ; GameObject.DestroyImmediate(tg.GetComponent<Button>()); tg.AddComponent<UIScaleButton>(); } } } } }
4.效果