UGUI实现NGUI的UIEventListener功能

在unity中处理UI事件时,习惯了使用NGUI的UIEventListener,虽然UGUI也有AddListener,但是一个组件只能对应一个函数,不能在一个函数中同时处理多个事件,显得有些麻烦

因为主要平时Button用得比较多,这里以UGUI的Button为例,自己以UGUI的Button的AddListener模仿NGUI的UIEventListener做了一个小封装,能在一个函数处理多个Button

using UnityEngine;
using UnityEngine.UI;
using System.Collections;

public class UGUIButtonEventListener : MonoBehaviour {

    public delegate void VoidDelegate(GameObject go);

    public VoidDelegate onClick;

    public static UGUIButtonEventListener GetClick(Button btn)
    {
        UGUIButtonEventListener listener = btn.GetComponent<UGUIButtonEventListener>();
        if (listener == null)
            listener = btn.gameObject.AddComponent<UGUIButtonEventListener>();
        btn.onClick.AddListener(listener.OnClick);
        return listener;
    }

    void OnClick()
    {
        if (onClick != null)
            onClick(gameObject);
    }
}
测试代码:

using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using UnityEngine.EventSystems;

public class test : MonoBehaviour
{
    public Button[] btns;
    void Start()
    {
        for (int i = 0; i < btns.Length; i++)
            UGUIButtonEventListener.Get(btns[i]).onClick = OnClick;
    }
    
    void OnClick(GameObject go)
    {
        print("name:"+go.name);
    }
}

还有人给了另一个Button事件监听的方法,感觉也挺好用

using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using UnityEngine.EventSystems;

public class test : MonoBehaviour
{
    public Button[] btns;
    void Start()
    {
        for (int i = 0; i < btns.Length; i++)
	{	
	    GameObject btnObj=btns[i].gameObject;
	    btns[i].onClick.AddListener(delegate(){OnClick(btnObj);});
	}
    }
    
    void OnClick(GameObject go)
    {
        print("name:"+go.name);
    }
}

但是UI事件肯定不止Button的Click事件,如果所有事件都按照上面的方法来封装就显得有些杂乱了。所以自己再去看了看UGUI的一些事件接口,发现通过实现接口,就能封装了,比如IPointerClickHandler,可以实现Click事件,IPointerEnterHandler、IPointerExitHandler可以实现Hover事件。后来再在网上查了一些资料,发现了EventTrigger已经继承了所有接口,正好可以用来封装UIEventListener

实现代码如下:

using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using UnityEngine.EventSystems;

public class UGUIEventListener:EventTrigger
{
    public delegate void VoidDelegate(GameObject go);
    public delegate void BoolDelegate(GameObject go, bool isValue);
    public delegate void FloatDelegate(GameObject go, float fValue);
    public delegate void IntDelegate(GameObject go, int iIndex);
    public delegate void StringDelegate(GameObject go, string strValue);

    public VoidDelegate onSubmit;
    public VoidDelegate onClick;
    public BoolDelegate onHover;
    public BoolDelegate onToggleChanged;
    public FloatDelegate onSliderChanged;
    public FloatDelegate onScrollbarChanged;
    public IntDelegate onDrapDownChanged;
    public StringDelegate onInputFieldChanged;

    public override void OnSubmit(BaseEventData eventData)
    {
        if (onSubmit != null)
            onSubmit(gameObject);
    }
    public override void OnPointerEnter(PointerEventData eventData)
    {
        if (onHover != null)
            onHover(gameObject, true);
    }
    public override void OnPointerClick(PointerEventData eventData)
    {
        if (onClick != null)
            onClick(gameObject);
        if (onToggleChanged != null)
            onToggleChanged(gameObject, gameObject.GetComponent<Toggle>().isOn);

    }
    public override void OnPointerExit(PointerEventData eventData)
    {
        if (onHover != null)
            onHover(gameObject, false);
    }
    public override void OnDrag(PointerEventData eventData)
    {
        if (onSliderChanged != null)
            onSliderChanged(gameObject, gameObject.GetComponent<Slider>().value);
        if (onScrollbarChanged != null)
            onScrollbarChanged(gameObject, gameObject.GetComponent<Scrollbar>().value);

    }
    public override void OnSelect(BaseEventData eventData)
    {
        if (onDrapDownChanged != null)
            onDrapDownChanged(gameObject, gameObject.GetComponent<Dropdown>().value);
    }
    public override void OnUpdateSelected(BaseEventData eventData)
    {
        if (onInputFieldChanged != null)
            onInputFieldChanged(gameObject, gameObject.GetComponent<InputField>().text);
    }
    public override void OnDeselect(BaseEventData eventData)
    {
        if (onInputFieldChanged != null)
            onInputFieldChanged(gameObject, gameObject.GetComponent<InputField>().text);
    }

    public static UGUIEventListener Get(GameObject go)
    {
        UGUIEventListener listener =go.GetComponent<UGUIEventListener>();
        if(listener==null) listener=go.AddComponent<UGUIEventListener>();
        return listener;
    }
}

测试代码如下:
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using UnityEngine.EventSystems;

public class test : MonoBehaviour
{
    public Button[] btns;
    public Scrollbar scrollbar;
    void Start()
    {
        for (int i = 0; i < btns.Length; i++)
            UGUIEventListener.Get(btns[i].gameObject).onClick = OnClick;
        UGUIEventListener.Get(scrollbar.gameObject).onScrollbarChanged = OnScrollbarChanged;
    }
    
    void OnClick(GameObject go)
    {
        print("name:"+go.name);
    }

    void OnScrollbarChanged(GameObject go, float value)
    {
        print("name:" + go.name + "  value:" + value);
    }
}

最后,还有一个小东西,因为自己在做一些测试的时候,发现UGUI的点击事件与3D物体的射线碰撞,是会发生冲突的,理论上,自己在点击UI的时候,3D物体的射线碰撞检测就会取消,不能让他们同时响应,这里用一个函数就可以判断EventSystem.current.IsPointerOverGameObject()

using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using UnityEngine.EventSystems;

public class test : MonoBehaviour
{
    void Update()
    {
	if (EventSystem.current.IsPointerOverGameObject())
		Debug.Log("鼠标在UI上");
	else
		Debug.Log("鼠标没在UI上");
    }
}
原文地址:https://www.cnblogs.com/liang123/p/6325899.html