起因:想使用UGUI给项目设计一个万能拖拽系统(2d-3d,3d-3d, 3d-2d),做了快两天了,完成度99%,但就是有点小BUG无法解决,天气又冷,烦恼。
静下心来,觉得还是对unity 的事件系统不熟悉,今晚坐下来读了读官网文档(终于),收获不小,写在这里,也算是一个记录:
Unity EventSystem
- Message System
- Input Modules
- Supported Events
- Raycasters
1. Message System(改进的消息系统)
基本上可以看成是以前SendMessage的升级版。
使用方法(照抄官网):
step1. 声明一个接口,继承自IEventSystemHandler
public interface ICustomMessageTarget : IEventSystemHandler
{
// functions that can be called via the messaging system
void Message1();
void Message2();
}
step2. 实现这个接口 , 把这个脚本挂在某个物体上,这里假设为物体AAA
public class CustomMessageTarget : MonoBehaviour, ICustomMessageTarget
{
public void Message1()
{
Debug.Log ("Message 1 received");
}
public void Message2()
{
Debug.Log ("Message 2 received");
}
}
step3. 在任何脚本中使用ExecuteEvents
静态类发送Message,来执行接口中定义的方法
//target should be AAA
ExecuteEvents.Execute(target, null, (x,y)=>x.Message1());
注意 : step3里的Excute泛型方法,有3个参数,第一个参数是发送message的gameobject对象,只有当对象上有IEventSystemHandler
实现类的时候才可以,这个例子中自然就是AAA物体。
还要注意 : ExecuteEvents静态类还有其他方法:
## Static Functions
EventSystems.ExecuteEvents.CanHandleEvent Can the given GameObject handle the IEventSystemHandler of type T.
EventSystems.ExecuteEvents.Execute Execute the event of type T : IEventSystemHandler on GameObject.
EventSystems.ExecuteEvents.ExecuteHierarchy Recurse up the hierarchy calling Execute until there is a GameObject that can handle the event.
EventSystems.ExecuteEvents.GetEventHandler Traverse the object hierarchy starting at root, and return the GameObject which implements the event handler of type
EventSystems.ExecuteEvents.ValidateEventData Attempt to convert the data to type T. If conversion fails an ArgumentException is thrown.
名字解释都比较直白,就不翻译了。比如那个EventSystems.ExecuteEvents.ExecuteHierarchy
, 是递归寻找适合的gameobject,并执行方法。
说实话,比以前的SendMessage科学了不少,以前只能在Hierarchy里上下求索,现在是有目的的寻找了。
但....我看来也就仅此而已了,SendMessage我在实际工程中从来都没用过,这个估计也不会用。为什么?有了System.Action谁还用这个...
2. Input Modules
此部分略,大致就是unity支持所有的输入方式,包括键盘啦,手柄啦,触摸啦等等,balabala...
3. Supported Events(支持的输入事件)
这部分就比较重要了,unity事件系统支持以下17种输入事件
事件接口 | 含义 |
---|---|
IPointerEnterHandler | pointer进入 |
IPointerExitHandler | pointer离开 |
IPointerDownHandler | pointer按下 |
IPointerUpHandler | pointer抬起 |
IPointerClickHandler | pointer按下和抬起 |
IInitializePotentialDragHandler | 可拖拽物体被发现,可用来初始化一些变量 |
IBeginDragHandler | 开始拖拽 |
IDragHandler | 拖拽中 |
IEndDragHandler | 拖拽结束时 (when) |
IDropHandler | 拖拽结束位置(where) |
IScrollHandler | 鼠标滚轮 |
IUpdateSelectedHandler | 选中物体时,持续发送 |
ISelectHandler | 物体变为被选择 |
IDeselectHandler | 物体变为取消选择 |
IMoveHandler | 物体移动(左右上下等) |
ISubmitHandler | submit(提交)按钮按下 |
ICancelHandler | cancel(取消)按钮按下 |
注意: 这里的“pointer”可以是鼠标、touch等一切unity支持的类型
那也就意味着,我们终于可以在PC和移动端共用一套代码了
4. Raycasters(射线们)
这也是另外一个重要的点:决定了unity对何种输入方式进行响应:
射线类型 | 含义 |
---|---|
Graphic Raycaster | UI使用 |
Physics 2D Raycaster | 2D 物体组件使用,如 BoxCollider2D等 |
Physics Raycaster | 3D物体使用(UI其实也能使用) |
5. Practice - 练习和测试
我们来建个简单的场景:
- 场景中增加一个空物体,命名为
EventSystem
,添加EventSystem
组件,点击组件上的Add Default Input Modules
按钮 - 场景中的摄像机上,添加
Physics Raycaster
组件 - 场景中建立一个3d的 Cude, 和一个2d的image
- 将以下脚本拖给Cude和Image:
using UnityEngine;
using UnityEngine.EventSystems;
public class SupportedEventsTest : MonoBehaviour,
IPointerEnterHandler, IPointerExitHandler, IPointerDownHandler, IPointerUpHandler,
IPointerClickHandler, IInitializePotentialDragHandler, IBeginDragHandler, IDragHandler,
IEndDragHandler, IDropHandler, IScrollHandler, IUpdateSelectedHandler,
ISelectHandler, IDeselectHandler, IMoveHandler, ISubmitHandler, ICancelHandler
{
public void OnBeginDrag(PointerEventData eventData)
{
Debug.Log("OnBeginDrag");
}
public void OnCancel(BaseEventData eventData)
{
Debug.Log("OnCancel");
}
public void OnDeselect(BaseEventData eventData)
{
Debug.Log("OnDeselect");
}
public void OnDrag(PointerEventData eventData)
{
Debug.Log("OnDrag");
}
public void OnDrop(PointerEventData eventData)
{
Debug.Log("OnDrop");
}
public void OnEndDrag(PointerEventData eventData)
{
Debug.Log("OnEndDrag");
}
public void OnInitializePotentialDrag(PointerEventData eventData)
{
Debug.Log("OnInitializePotentialDrag");
}
public void OnMove(AxisEventData eventData)
{
Debug.Log("OnMove");
}
public void OnPointerClick(PointerEventData eventData)
{
Debug.Log("OnPointerClick");
}
public void OnPointerDown(PointerEventData eventData)
{
Debug.Log("OnPointerDown");
}
public void OnPointerEnter(PointerEventData eventData)
{
Debug.Log("OnPointerEnter");
}
public void OnPointerExit(PointerEventData eventData)
{
Debug.Log("OnPointerExit");
}
public void OnPointerUp(PointerEventData eventData)
{
Debug.Log("OnPointerUp");
}
public void OnScroll(PointerEventData eventData)
{
Debug.Log("OnScroll");
}
public void OnSelect(BaseEventData eventData)
{
Debug.Log("OnSelect");
}
public void OnSubmit(BaseEventData eventData)
{
Debug.Log("OnSubmit");
}
public void OnUpdateSelected(BaseEventData eventData)
{
Debug.Log("OnUpdateSelected");
}
}
运行游戏,我们可以看到,3d和2d物体都可以相应事件系统,这是由于我们给摄像机添加了Physics Raycaster
组件。如果你换成Graphic Raycaster
,那Cube是不会响应的。
好,今天就写到这,写的还算整齐,睡觉了。
╮(╯3╰)╭睡眠不足,不熬夜不追剧( ̄▽ ̄)*