很多时候我们写一些公共工具或者通用脚本时,需要跟Unity组件一样实现某些功能,例如Button组件上的Transition选择之后会变化出相对应的模块。那么这个功能怎么实现呢?其实Unity提供了这种功能实现的方法,那就是Attribute标签,标记特性类。想具体知道是怎么实现的可以看下官方文档或者一些关于Attribute的博客。
实现
实现一个通用的鼠标对button移入移出切换图片或者显示/隐藏物体脚本。
首先,把自己要实现的功能脚本写完,我这里写的是对button移入移出的简单脚本
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
namespace Util
{
public enum Mode
{
/// <summary>
/// UI事件
/// </summary>
UISprite,
/// <summary>
/// 物体隐藏显示
/// </summary>
UIObject,
}
public class UIEnterEvent : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler, IPointerClickHandler
{
[Header("选择模式")] [SerializeField] private Mode uiMode;
//----------Object操作----------------
[Header("移入时")] [SerializeField] private GameObject enterObj;
[Header("移出时")] [SerializeField] private GameObject exitObject;
//----------UI操作-----------------------
[Header("移入时")] [SerializeField] private Sprite enterSpr;
[Header("移出时")] [SerializeField] private Sprite exitSpr;
[Header("点击时")] [SerializeField] private Sprite clickSpr;
private void OnDisable()
{
if (uiMode == Mode.UISprite && exitSpr != null)
{
GetComponent<Image>().sprite = exitSpr;
}
}
public void OnPointerEnter(PointerEventData eventData)
{
if (uiMode == Mode.UISprite && enterSpr != null)
{
GetComponent<Image>().sprite = enterSpr;
}
if (uiMode == Mode.UIObject && enterObj != null)
{
enterObj.SetActive(true);
}
}
public void OnPointerExit(PointerEventData eventData)
{
if (uiMode == Mode.UISprite && exitSpr != null)
{
GetComponent<Image>().sprite = exitSpr;
}
if (uiMode == Mode.UIObject && exitObject != null)
{
exitObject.SetActive(false);
}
}
public void OnPointerClick(PointerEventData eventData)
{
if (uiMode == Mode.UISprite && clickSpr != null)
{
GetComponent<Image>().sprite = clickSpr;
}
}
}
}
Enum Mode就是等会需要用到切换方式的枚举,通过这个枚举来确定我们这个脚本具体实现的功能。
下面就来定义一个Attribute特性类,因为需要在编辑器下运行所以要写在editor下。
[CustomEditor(typeof(UIEnterEvent))] 定义好这个标签就可以实现想要的功能。
using System;
using UnityEngine;
using UnityEditor;
using Util;
[CustomEditor(typeof(UIEnterEvent))]
public class ComponentInspectorEditor : Editor
{
private SerializedObject object;
private SerializedProperty _PropertyEnum;
//OBJ属性
private SerializedProperty _EnterObj;
private SerializedProperty _ExitObj;
//UI属性
private SerializedProperty _EnterSp;
private SerializedProperty _ExitSp;
private SerializedProperty _ClickSp;
private void OnEnable()
{
object = new SerializedObject(target);
_PropertyEnum = object.FindProperty("uiMode");
//obj
_EnterObj = object.FindProperty("enterObj");
_ExitObj = object.FindProperty("exitObject");
//ui
_EnterSp = object.FindProperty("enterSpr");
_ExitSp = object.FindProperty("exitSpr");
_ClickSp = object.FindProperty("clickSpr");
}
public override void OnInspectorGUI()
{
EditorGUILayout.PropertyField(_PropertyEnum);
//枚举 = UIObject时 打开物体属性面板
if (_PropertyEnum.enumValueIndex == 1)
{
EditorGUILayout.PropertyField(_EnterObj);
EditorGUILayout.PropertyField(_ExitObj);
}
//枚举 = UISprite时 打开UI属性面板
if (_PropertyEnum.enumValueIndex == 0)
{
EditorGUILayout.PropertyField(_EnterSp);
EditorGUILayout.PropertyField(_ExitSp);
EditorGUILayout.PropertyField(_ClickSp);
}
object.ApplyModifiedProperties();
}
}
结果