总结下从网上看到的大部分Button添加事件的方法,总结了有9种,中间原理可能有重复的,最后是一些注意事项
一.Inspector面板拖拽添加无参函数
1.Hierarchy窗口建立一个空物体
2.创建Button和一个空物体GameObject
3.创建脚本DTPractice,挂在GameObject上
DTPractice.cs
public class DTPractice : MonoBehaviour{
public void OnClickBtn1()
{
Debug.Log("Click1");
}
}
Button上的设置:
运行结果:
二.Inspector面板拖拽添加有参函数
和第一中方法一样,只是在公有函数中添加参数
DTPractice.cs
public class DTPractice : MonoBehaviour{
public void OnClickBtn2(int i)
{
Debug.Log("Click2"+"参数"+i);
}
}
再Button的Inspector界面设置:
输入对应参数,运行结果:
上面两种方法都必须是公有的
三.使用AddListener添加无参的回调函数
1.DTPractice.cs脚本绑定在GameObject空物体上
2.使用拖拽将Button赋值到DTPractice脚本中
DTPractice.cs
public class DTPractice : MonoBehaviour{
public GameObject btn3;
private void Start()
{
btn3.GetComponent
或者直接输出
public class DTPractice : MonoBehaviour{
public GameObject btn3;
private void Start()
{
btn3.GetComponent
输出结果:
相同原理的方法:本质就是获得Button组件
1).DTPractice.cs脚本绑定在Button上
DTPractice.cs
public class DTPractice : MonoBehaviour{
private Button btn6;
private void Start()
{
btn6 = GetComponent
另一个脚本 Test.cs,绑定再GameObject空物体上
public class Test : MonoBehaviour {
public void OnClickBtn6()
{
Debug.Log("Click6");
}
运行结果:
2).或者通过名字查找获得Button组件进行监听
DTPractice.cs绑定在GameObject空物体上
public class DTPractice : MonoBehaviour{
private Button btn6;
private void Start()
{
btn6 = GameObject.Find("Button").GetComponent
四.使用AddListener添加有参数的回调函数
拖拽方式和方法三相同
DTPractice.cs
public class DTPractice : MonoBehaviour{
public GameObject btn3;
private void Start()
{
btn3.GetComponent
运行结果:
五.自定义一个类继承自EventTrigger,并重写其中部分所需要的方法(可以延伸到UGUI中的各种事件)
先看下NGUI中的EventTriggerListener脚本
1.using UnityEngine;
2.using UnityEngine.EventSystems;
3.
4.public class EventTriggerListener : EventTrigger
5.{
6. public delegate void VoidDelegate(GameObject go);
7. public VoidDelegate onClick;
8. public VoidDelegate onDown;
9. public VoidDelegate onEnter;
10. public VoidDelegate onExit;
11. public VoidDelegate onUp;
12. public VoidDelegate onSelect;
13. public VoidDelegate onUpdateSelect;
14. public VoidDelegate onDrag;
15. public VoidDelegate onDrop;
16. public VoidDelegate onDeselect;
17. public VoidDelegate onScroll;
18. public VoidDelegate onMove;
19. public VoidDelegate onInitializePotentialDrag;
20. public VoidDelegate onBeginDrag;
21. public VoidDelegate onEndDrag;
22. public VoidDelegate onSubmit;
23. public VoidDelegate onCancel;
24.
25. public override void OnPointerClick(PointerEventData eventData)
26. {
27. if (onClick != null) onClick(gameObject);
28. }
29. public override void OnPointerDown(PointerEventData eventData)
30. {
31. if (onDown != null) onDown(gameObject);
32. }
33. public override void OnPointerEnter(PointerEventData eventData)
34. {
35. if (onEnter != null) onEnter(gameObject);
36. }
37. public override void OnPointerExit(PointerEventData eventData)
38. {
39. if (onExit != null) onExit(gameObject);
40. }
41. public override void OnPointerUp(PointerEventData eventData)
42. {
43. if (onUp != null) onUp(gameObject);
44. }
45. public override void OnSelect(BaseEventData eventData)
46. {
47. if (onSelect != null) onSelect(gameObject);
48. }
49. public override void OnUpdateSelected(BaseEventData eventData)
50. {
51. if (onUpdateSelect != null) onUpdateSelect(gameObject);
52. }
53.
54. public override void OnDrag(PointerEventData eventData)
55. {
56. if (onDrag != null) onDrag(gameObject);
57. }
58.
59. public override void OnDrop(PointerEventData eventData)
60. {
61. if (onDrop != null) onDrop(gameObject);
62. }
63.
64. public override void OnDeselect(BaseEventData eventData)
65. {
66. if (onDeselect != null) onDeselect(gameObject);
67. }
68.
69. public override void OnScroll(PointerEventData eventData)
70. {
71. if (onScroll != null) onScroll(gameObject);
72. }
73.
74. public override void OnMove(AxisEventData eventData)
75. {
76. if (onMove != null) onMove(gameObject);
77. }
78.
79. public override void OnInitializePotentialDrag(PointerEventData eventData)
80. {
81. if (onInitializePotentialDrag != null) onInitializePotentialDrag(gameObject);
82. }
83.
84. public override void OnBeginDrag(PointerEventData eventData)
85. {
86. if (onBeginDrag != null) onBeginDrag(gameObject);
87. }
88.
89. public override void OnEndDrag(PointerEventData eventData)
90. {
91. if (onEndDrag != null) onEndDrag(gameObject);
92. }
93.
94. public override void OnSubmit(BaseEventData eventData)
95. {
96. if (onSubmit != null) onSubmit(gameObject);
97. }
98.
99. public override void OnCancel(BaseEventData eventData)
100. {
101. if (onCancel != null) onCancel(gameObject);
102. }
103.
104. ///
105. /// 获取或添加一个事件侦听器到指定的游戏对象。用法和NGUI一样
106. ///
107.
108. public static EventTriggerListener Get(GameObject go)
109. {
110. EventTriggerListener listener = go.GetComponent();
111. if (listener == null) listener = go.AddComponent();
112. return listener;
113. }
}
NGUI底层就是封装了这个方法,所以在按钮动态添加事件的时候调用的就是上面脚本中的方法
同理写一个类似上面的脚本,用于UGUI
UGUI所提供的EventTrigger类如下:
涉及到各种操作函数,继承重写的时候只需要些能用到的函数,此处重写OnPointClick函数即可
创建EventTriggerListener.cs脚本,继承字EventTrigger,该脚本不需要挂在场景中物体上也挂不了
public class EventTriggerListener : EventTrigger{
public delegate void ClickListener();
public ClickListener onClick;
///
/// 从某个物体上获得EventTriggerListener脚本,没有的话添加该脚本
///
/// //可以将参数换成GameObject类型,就和NGUI中动态添加回调函数的方法一样了
///
public static EventTriggerListener Get(Transform trans) {
EventTriggerListener listener = trans.GetComponent();
if (listener==null)
{
listener = trans.gameObject.AddComponent();
}
return listener;
}
///
/// 重写EventTrigger中该函数
///
///
public override void OnPointerClick(PointerEventData eventData)
{
if (onClick != null)
onClick();//调用委托
}
}
DTPractice.cs脚本进行测试,绑定在GameObject空物体上,btn5通过拖拽进行赋值
public class DTPractice : MonoBehaviour{
public GameObject btn5;
private void Start()
{
EventTriggerListener.Get(btn5.transform).onClick += OnClickBtn5;
}
void OnClickBtn5()
{
Debug.Log("Click5");
}
}
运行结果:
此方法的好处在于,可以实现UGUI提供的OnClick事件之外的事件如:OnPointDown(按下事件),OnPointExit(抬起事件)等,根据自己需求获取
六.通过EventTrigger实现按钮的点击事件,方法5是通过重写EventTrigger中的函数来进行,方法6直接使用EventTrigger来进行操作
DTPractice.cs脚本,绑定在Button按钮上,运行即可
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using DG.Tweening;
using UnityEngine.UI;
using UnityEngine.EventSystems;
[RequireComponent(typeof(EventTrigger))]
public class DTPractice : MonoBehaviour{
private void Start()
{
Button btn6 = this.GetComponent
运行结果:
也可以和方法五一样协程不同的事件状态
七.EventTrigger再Inspector界面添加实现按钮点击事件
按钮Button上添加EventTrigger组件,点击AddNewEventType,添加EventTrigger中的函数,然后进行拖拽赋值
DTPractice.cs脚本绑定在GameObject空物体上
DTPractice.cs
public class DTPractice : MonoBehaviour{
public void M()
{
Debug.Log("鼠标点击");
}
public void N()
{
Debug.Log("鼠标进入");
}
public void F()
{
Debug.Log("鼠标滑出");
}
}
Inspector界面添加:
运行结果:
八.继承基础接口实现Button回调事件添加
UGUI的EventTrigger中可以看到是继承了很多的基础接口,做了一个封装,我们可以直接继承这些基础接口来实现功能
DTPractice.cs 脚本绑定在Button上
DTPractice.cs
public class DTPractice : MonoBehaviour,IPointerClickHandler{
public void OnPointerClick(PointerEventData data)
{
Debug.Log("Click8");
}
}
运行结果:
九.方法八的扩展,一个按钮的时候这么写可以,当界面中有多个按钮的时候使用一个观察者模式进行处理
写一个观察者类脚本UIEventListener.cs 实现所有基础接口,多个按钮来注册这个观察类脚本中的事件,就不用每个按钮都需要继承基础接口类,简化操作
UIEventListener.cs
public class UIEventListener : MonoBehaviour ,IPointerClickHandler,IPointerEnterHandler,IPointerExitHandler{
public delegate void UIEventProxy(GameObject obj);//一个委托对应多个事件
public event UIEventProxy OnClick;
public event UIEventProxy OnMouseEnter;
public event UIEventProxy OnMouseExit;
public void OnPointerClick(PointerEventData data)
{
if (OnClick != null)
OnClick(this.gameObject);
}
public void OnPointerEnter(PointerEventData data)
{
if (OnMouseEnter != null)
OnMouseEnter(this.gameObject);
}
public void OnPointerExit(PointerEventData data)
{
if (OnMouseExit != null)
OnMouseExit(this.gameObject);
}
}
Test.cs脚本绑定在Button上,注册UIEventListener脚本中的事件
public class Test : MonoBehaviour {
private void Start()
{
Button btn = this.GetComponent
运行结果:
十.注意事项:
1.AddListener每次调用的时候都会添加一个监听,不能放在Update中
2.如果脚本是DontDestroyOnLoad,记得再AddListener之前加上RemoveAllListener
3.如果不想移除按钮所有事件,可以使用button.OnClick.RemoveListener(btnAction)来移除指定事件,其中参数是UnityAction类型的
4.使用EventTrigger中的AddEventType添加事件,监听分解动作
各种Event触发的机理和时机:
①PointerEnter:指针(鼠标、手指等)进入目标(Button、Panel等)范围的瞬间;
②PointerExit:指针离开目标范围的瞬间;
③PointerDown:指针在目标范围内时:按下的瞬间;
④PointerUp:指针在目标范围内时:指针抬起的瞬间:即使指针抬起的瞬间不在目标范围内,也会触发;
⑤PointerClick:指针对目标完成一次点击的瞬间:如果指针抬起的瞬间不在目标范围内,便不会触发;在PointerUp之后执行;
⑥Drag:指针按住并移动时:如果按下不移动则不触发;即使拖动时指针不在目标范围内也会触发;
⑦Drop:(理解为有其他东西被扔到监听对象身上时触发)在指针抬起的瞬间:如果被拖拽目标A此时在另一目标B的范围内,并且目标B有对Drop的监听(目标A不需要,但需要能够Drag),则触发;否则不会触发;在PointerUp之后执行;
⑧Scroll:指针在目标范围内时:无论指针是否按下,滚动滚轮时触发;
⑨UpdateSelected:指针完成一次PointerClick后,每一帧都会执行一次对应事件(下文的Select只在最开始执行一次);
⑩Select:指针在目标范围内完成第一次点击后,目标变为"Select"状态;
⑪Deselect:指针在目标范围外完成第一次点击后,目标变为"Deselect"状态;
⑫Move:任意目标处于"Select"状态下时:通过『上』『下』『左』『右』键,或"W", "S", "A", "D" 等键改变了Axis轴的Value时触发(可用Input.GetAxis("AxisName")检测);
⑬InitializePotentialDrag:指针在目标范围内按下时:初始化潜在的可拖动目标,在PointerDown之后,BeginDrag之前触发;
⑭BeginDrag:指针在目标范围内按下时:一旦移动便触发;即使拖动时指针不在目标范围内也会触发;
⑮EndDrag:指针在移动时抬起的瞬间:即使指针不在目标范围内也会触发;如果触发了Drop则在其之后触发;
⑯Submit:目标处于"Select"状态下时:点击"Submit"键(默认为"Enter"键)时触发;
⑰Cancel:目标处于"Select"状态下时:点击"Cancel"键(默认为"ESC"键)时触发;
都是在网上看到的方法,做个汇总而已。