UGUI接口的实现和触发条件简记

UnityEngine.EventSystems

介绍

这是我最常用到的一些接口。当UGUI本身提供的一些脚本无法实现需求时,我就会用以下的接口组合成一个适合的脚本。
其中可以大体的分为以下几个部分:

Pointer鼠标指针点击接口

  • IPointerEnterHandler指针进入
  • IPointerDownHandler指针按下
  • IPointerClickHandler指针点击
  • IPointerUpHandler指针抬起
  • IPointerExitHandler指针离开

Drag拖拽接口

  • IBeginDragHandler拖动开始
  • IDragHandler拖动
  • IEndDragHandler拖动结束
  • IDropHandler接收拖动
  • IInitializePotentialDragHandler初始化潜在的拖动

选择组事件

必须设置选择对象后才能触发EventSystem.current.SetSelectedGameObject(gameobject)

  • ISelectHandler选择
  • IDeselectHandler取消选择
  • IUpdateSelectedHandler选中的物体每帧触发

滚轮滚动

  • IScrollHandler

InputManager关联组事件(同选择组要求)

  • IMoveHandler移动(Horizontal和Vertical按键)
  • ICancelHandlerEsc键
  • ISubmitHandlerEnter键

代码

using UnityEngine;
using UnityEngine.EventSystems;

public class UGUITest : MonoBehaviour,
    IPointerEnterHandler, IPointerDownHandler, IPointerClickHandler, IPointerUpHandler, IPointerExitHandler,
    IBeginDragHandler, IDragHandler, IEndDragHandler, IDropHandler, IInitializePotentialDragHandler,
    ISelectHandler, IDeselectHandler, IUpdateSelectedHandler,
    IScrollHandler,
    IMoveHandler, ICancelHandler, ISubmitHandler
{
    #region Pointer
    /// <summary>
    /// 指针进入事件
    /// ------
    /// 当鼠标光标移入该对象时触发
    /// </summary>
    /// <param name="eventData"></param>
    public virtual void OnPointerEnter(PointerEventData eventData) { Debug.Log("PointerEnter"); }
    /// <summary>
    /// 指针按下事件
    /// ------
    /// 鼠标点击A对象,按下鼠标时A对象响应此事件
    /// </summary>
    /// <param name="eventData"></param>
    public virtual void OnPointerDown(PointerEventData eventData) { Debug.Log("PointerDown"); }
    /// <summary>
    /// 指针点击事件
    /// ------
    /// 在组件可视的区域按下且抬起时指针处于区域内(按下离开区域后抬起不会触发)
    /// </summary>
    /// <param name="eventData"></param>
    public virtual void OnPointerClick(PointerEventData eventData) { Debug.Log("PointerClick"); }
    /// <summary>
    /// 指针抬起事件
    /// ------
    /// 鼠标点击A对象,抬起鼠标时响应,无论鼠标在何处抬起(即不在A对象中),都会在A对象中响应此事件
    /// 注:响应此事件的前提是A对象必须响应过OnPointerDown事件
    /// </summary>
    /// <param name="eventData"></param>
    public virtual void OnPointerUp(PointerEventData eventData) { Debug.Log("PointerUp"); }
    /// <summary>
    /// 指针离开事件
    /// ------
    /// 当鼠标光标移出该对象时触发
    /// </summary>
    /// <param name="eventData"></param>
    public virtual void OnPointerExit(PointerEventData eventData) { Debug.Log("PointerExit"); }
    #endregion

    #region Drag
    /// <summary>
    /// 拖动开始事件
    /// ------
    /// 当鼠标在A对象按下后,不抬起,开始拖拽时 A对象响应此事件
    /// 此事件在OnInitializePotentialDrag之后响应 OnDrag之前响应
    /// </summary>
    /// <param name="eventData"></param>
    public virtual void OnBeginDrag(PointerEventData eventData) { Debug.Log("BeginDrag"); }
    /// <summary>
    /// 拖动中事件
    /// ------
    /// 当鼠标拖拽A对象时,A对象每帧响应一次此事件
    /// 注:如果不实现此接口,则后面的三个接口方法都不会触发
    /// </summary>
    /// <param name="eventData"></param>
    public virtual void OnDrag(PointerEventData eventData) { Debug.Log("Drag"); }
    /// <summary>
    /// 拖动结束事件
    /// ------
    /// 当鼠标拖拽A对象后,鼠标抬起时 A对象响应此事件
    /// </summary>
    /// <param name="eventData"></param>
    public virtual void OnEndDrag(PointerEventData eventData) { Debug.Log("EndDrag"); }
    /// <summary>
    /// 接收拖动事件
    /// ------
    /// A、B对象必须均实现IDropHandler接口,且A至少实现IDragHandler接口
    /// 当鼠标从A对象上开始拖拽,在B对象上抬起时 B对象响应此事件
    /// 此时name获取到的是B对象的name属性
    /// eventData.pointerDrag表示发起拖拽的对象(GameObject)
    /// </summary>
    /// <param name="eventData"></param>
    public virtual void OnDrop(PointerEventData eventData) { Debug.Log("Drop"); }
    /// <summary>
    /// 初始化潜在的拖动事件
    /// ------
    /// 当鼠标在A对象按下还没开始拖拽时 A对象响应此事件
    /// 注:此接口事件与IPointerDownHandler接口事件类似
    /// 二者的执行顺序:先执行IPointerDownHandler,然后执行此接口事件
    /// </summary>
    /// <param name="eventData"></param>
    public virtual void OnInitializePotentialDrag(PointerEventData eventData) { Debug.Log("InitializePotentialDrag"); }
    #endregion

    #region 选择组事件
    /***必须设置选择对象后才能触发--EventSystem.current.SetSelectedGameObject(gameobject)***/
    /// <summary>
    /// 选择事件
    /// </summary>
    /// <param name="eventData"></param>
    public virtual void OnSelect(BaseEventData eventData) { Debug.Log("Select"); }
    /// <summary>
    /// 取消选择事件
    /// </summary>
    /// <param name="eventData"></param>
    public virtual void OnDeselect(BaseEventData eventData) { Debug.Log("Deselect"); }
    /// <summary>
    /// 选中物体每帧触发事件
    /// </summary>
    /// <param name="eventData"></param>
    public virtual void OnUpdateSelected(BaseEventData eventData) { Debug.Log("UpdateSelected"); }
    #endregion

    /// <summary>
    /// 滚动事件
    /// ------
    /// 滑轮在上面滚动时触发
    /// </summary>
    /// <param name="eventData"></param>
    public virtual void OnScroll(PointerEventData eventData) { Debug.Log("Scroll"); }


    #region InputManager关联组事件(同选择组要求)
    /// <summary>
    /// 移动事件(上下左右)
    /// ------
    /// 与InputManager里的Horizontal和Vertical按键相对应。Input.GetAxisRaw
    /// </summary>
    /// <param name="eventData"></param>
    public virtual void OnMove(AxisEventData eventData) { Debug.Log("Move"); }
    /// <summary>
    /// 取消事件
    /// ------
    /// 按下InputManager里的Cancel对应的按键(PC、Mac默认:Esc键)。Input.GetButtonDown
    /// </summary>
    /// <param name="eventData"></param>
    public virtual void OnCancel(BaseEventData eventData) { Debug.Log("Cancel"); }
    /// <summary>
    /// 提交事件
    /// ------
    /// 按下InputManager里的Submit对应的按键(PC、Mac默认:Enter键)。Input.GetButtonDown
    /// </summary>
    /// <param name="eventData"></param>
    public virtual void OnSubmit(BaseEventData eventData) { Debug.Log("Submit"); }
    #endregion
}

示例

有一个相关示例,附上链接:https://blog.csdn.net/f_957995490/article/details/103928986

UnityEngine.UI

下面的接口我也没有用过多少,但网文中有就测试了几个,简单记录。

IMaterialModifier

using UnityEngine;
using UnityEngine.UI;

/// <summary>
/// 材质修改接口
/// </summary>
public class MaterialModifier : MonoBehaviour, IMaterialModifier
{
    public Material GetModifiedMaterial(Material baseMaterial)
    {
        Debug.Log("IMaterialModifier.GetModifiedMaterial");
        Debug.Log(baseMaterial);
        return null;
    }

    public Material m_material = null;

    private void Awake()
    {
        Debug.Log(GetModifiedMaterial(m_material));
    }
}

无论是在编辑还是运行情况下,只要改变UI中的材质,便会被调用,函数中的参数baseMaterial便是要改变的目标材质

ICanvasRaycastFilter

using UnityEngine;

/// <summary>
/// 光线投射过滤器
/// </summary>
public class CanvasRaycastFilter : MonoBehaviour, ICanvasRaycastFilter
{
    public bool IsRaycastLocationValid(Vector2 sp, Camera eventCamera)
    {
        Debug.Log("ICanvasRaycastFilter.IsRaycastLocationValid");
        Debug.Log(sp + "  " + eventCamera.name);
        return false;
        //throw new NotImplementedException();
    }
}

运行时,只要鼠标在该UI对象的范围内,便会被持续调用。其中参数sp为屏幕坐标系下光标的实时坐标参数eventCamera为,管理该UI对象的Canvas组件中所记录的Camera对象,如果Canvas组件的Render Mode属性是在Screen Space_Overlay状态时,该参数则是为空(NULL)值

ICanvasElement

using System;
using UnityEngine;
using UnityEngine.UI;

/// <summary>
/// 需要canvas绘制的对象都实现该接口,如text, image等
/// </summary>
public class CanvasElement : MonoBehaviour, ICanvasElement
{
    Transform ICanvasElement.transform
    {
        get
        {
            Debug.Log("ICanvasElement.transform");
            throw new NotImplementedException();
        }
    }

    void ICanvasElement.GraphicUpdateComplete()
    {
        Debug.Log("ICanvasElement.GraphicUpdateComplete");
        throw new NotImplementedException();
    }

    bool ICanvasElement.IsDestroyed()
    {
        Debug.Log("ICanvasElement.IsDestroyed");
        throw new NotImplementedException();
    }

    void ICanvasElement.LayoutComplete()
    {
        Debug.Log("ICanvasElement.LayoutComplete");
        throw new NotImplementedException();
    }

    void ICanvasElement.Rebuild(CanvasUpdate executing)
    {
        Debug.Log("ICanvasElement.Rebuild");
        throw new NotImplementedException();
    }
}

IClippable

using System;
using UnityEngine;
using UnityEngine.UI;

/// <summary>
/// 可裁剪功能
/// </summary>
public class Clippable : MonoBehaviour, IClippable
{
    public RectTransform rectTransform
    {
        get
        {
            Debug.Log("IClippable.rectTransform");
            throw new NotImplementedException();
        }
    }

    public void Cull(Rect clipRect, bool validRect)
    {
        Debug.Log("IClippable.Cull");
        throw new NotImplementedException();
    }

    public void RecalculateClipping()
    {
        Debug.Log("IClippable.RecalculateClipping");
        throw new NotImplementedException();
    }

    public void SetClipRect(Rect value, bool validRect)
    {
        Debug.Log("IClippable.SetClipRect");
        throw new NotImplementedException();
    }
}

IClipper

using System;
using UnityEngine;
using UnityEngine.UI;

/// <summary>
/// 执行裁切功能接口
/// </summary>
public class Clipper : MonoBehaviour, IClipper
{
    void IClipper.PerformClipping()
    {
        Debug.Log("IClipper.PerformClipping");
        throw new NotImplementedException();
    }
}

ILayoutController / ILayoutGroup:ILayoutController / ILayoutGroup:ILayoutController

using UnityEngine;
using UnityEngine.UI;

/// <summary>
/// 渲染时和IMaterialModifier以其调用的
/// </summary>
public class LayoutController : MonoBehaviour, ILayoutController
{
    public void SetLayoutHorizontal()
    {
        Debug.Log("ILayoutController.SetLayoutHorizontal");
    }
    
    public void SetLayoutVertical()
    {
        Debug.Log("ILayoutController.SetLayoutVertical");
    }
}

ILayoutElement

using System;
using UnityEngine;
using UnityEngine.UI;

/// <summary>
/// 布局元素的接口功能
/// </summary>
public class LayoutElement : MonoBehaviour, ILayoutElement
{
    public float flexibleHeight
    {
        get
        {
            Debug.Log("ILayoutElement.flexibleHeight");
            throw new NotImplementedException();
        }
    }

    float ILayoutElement.flexibleWidth
    {
        get
        {
            Debug.Log("ILayoutElement.flexibleWidth");
            throw new NotImplementedException();
        }
    }

    int ILayoutElement.layoutPriority
    {
        get
        {
            Debug.Log("ILayoutElement.layoutPriority");
            throw new NotImplementedException();
        }
    }

    float ILayoutElement.minHeight
    {
        get
        {
            Debug.Log("ILayoutElement.minHeight");
            throw new NotImplementedException();
        }
    }

    float ILayoutElement.minWidth
    {
        get
        {
            Debug.Log("ILayoutElement.minWidth");
            throw new NotImplementedException();
        }
    }

    float ILayoutElement.preferredHeight
    {
        get
        {
            Debug.Log("ILayoutElement.preferredHeight");
            throw new NotImplementedException();
        }
    }

    float ILayoutElement.preferredWidth
    {
        get
        {
            Debug.Log("ILayoutElement.preferredWidth");
            throw new NotImplementedException();
        }
    }

    void ILayoutElement.CalculateLayoutInputHorizontal()
    {
        Debug.Log("ILayoutElement.CalculateLayoutInputHorizontal");
    }

    void ILayoutElement.CalculateLayoutInputVertical()
    {
        Debug.Log("ILayoutElement.CalculateLayoutInputVertical");
    }
}

ILayoutIgnorer

using System;
using UnityEngine;
using UnityEngine.UI;

public class LayoutIgnorer : MonoBehaviour, ILayoutIgnorer
{
    public bool ignoreLayout
    {
        get
        {
            Debug.Log("ILayoutIgnorer.ignoreLayout");
            throw new NotImplementedException();
        }
    }
}

IMaskable

using System;
using UnityEngine;
using UnityEngine.UI;

/// <summary>
/// 透明遮罩接口
/// </summary>
public class Maskable : MonoBehaviour, IMaskable
{
    void IMaskable.RecalculateMasking()
    {
        Debug.Log("IMaskable.RecalculateMasking");
        throw new NotImplementedException();
    }
}

除了最前面两个接口,其他的暂时没有时间测试出结果。

发布了20 篇原创文章 · 获赞 1 · 访问量 923

猜你喜欢

转载自blog.csdn.net/f_957995490/article/details/103928846
今日推荐