Unity自带的Button组件有三种不同的Transition(过渡)选项,分别是None, ColorTint, SpriteSwap, Animation。现在想自定义其他功能,比如在不同的状态下,按钮上的文字不同。
首先想到的是直接写一个脚本挂在Button上,实现UnityEngine.EventSystems中定义的IPointerEnterHandler, IPointerExitHandler, IPointerClickHandler这三个接口,代码如下:
public class MyButton1 : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler, IPointerClickHandler { [SerializeField] private Button button; [SerializeField] private Text text; private void Start() { if(button == null) { button = GetComponent<Button>(); } if(text == null) { text = GetComponentInChildren<Text>(); } } public void OnPointerEnter(PointerEventData eventData) { Debug.Log("Pointer enter"); text.text = "Pointer enter"; } public void OnPointerExit(PointerEventData eventData) { Debug.Log("Pointer Exit"); text.text = "Pointer Exit"; } public void OnPointerClick(PointerEventData eventData) { Debug.Log("Pointer click"); text.text = "Pointer click"; } }
实际上Button自身已经实现了这几个接口,所以可以直接继承Button并重写这三个方法,将原来的Button组件换成MyButton2:
public class MyButton2 : Button { [SerializeField] private Text text; protected override void Awake() { base.Awake(); if(text == null) { text = GetComponentInChildren<Text>(); } } public override void OnPointerEnter(PointerEventData eventData) { base.OnPointerEnter(eventData); Debug.Log("Pointer enter"); text.text = "Pointer enter"; } public override void OnPointerExit(PointerEventData eventData) { base.OnPointerExit(eventData); Debug.Log("Pointer Exit"); text.text = "Pointer Exit"; } public override void OnPointerClick(PointerEventData eventData) { base.OnPointerClick(eventData); Debug.Log("Pointer click"); text.text = "Pointer click"; } }
这时候会发现继承自Button的MyButton2在Inspector里并不能看到text字段,这时需要对Button的编辑器显示进行扩展:
using UnityEditor; using UnityEditor.UI; [CustomEditor(typeof(MyButton2), true)] [CanEditMultipleObjects] public class MyButton2Editor : ButtonEditor { private SerializedProperty text; protected override void OnEnable() { base.OnEnable(); text = serializedObject.FindProperty("text"); } public override void OnInspectorGUI() { base.OnInspectorGUI(); EditorGUILayout.Space(); serializedObject.Update(); EditorGUILayout.PropertyField(text); serializedObject.ApplyModifiedProperties(); } }
(将上面这个脚本放到Assets>Editor文件夹下,这样只是在编辑器里使用,不会被打包发布)
其实也可以直接重写Button的DoStateTransition这个方法,对应的就是Button组件显示在Inspector里的Transition:
public class MyButton3 : Button { [SerializeField] private Text text; protected override void Awake() { base.Awake(); if(text == null) { text = GetComponentInChildren<Text>(); } } protected override void DoStateTransition(SelectionState state, bool instant) { switch(state) { case SelectionState.Normal: Debug.Log("Normal"); text.text = "Normal"; break; case SelectionState.Pressed: Debug.Log("Pressed"); text.text = "Pressed"; break; case SelectionState.Highlighted: Debug.Log("Highlited"); text.text = "Highlited"; break; case SelectionState.Disabled: Debug.Log("Disabled"); text.text = "Disabled"; break; } } }
按照这个思路还可以实现更多的效果。