在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上"); } }