2019独角兽企业重金招聘Python工程师标准>>>

UGUI是Unity3D官方推出的UI系统,为了更好的使用UGUI,我们就需要去了解它。

UGUI代码开源,我们可以从bitbucket下载到源码。

虽然Unity官方喜欢藏着掖着,例如RectTransform和Canvas系列的源码都放在了UnityEngine里面,但是这并不妨碍我们对已开源的代码进行分析(其实多少也有些妨碍吧。。。)

今天我们就探究了一下UGUI的事件系统EventSystem。

虽然名字起得很大,但是实际上EventSystem处理和管理的其实是点击、键盘输入、触摸等事件,所以应该成为输入事件系统InputEventSystem更为恰当。

我们看到EventSystem最开始声明了一个List和一个变量

[csharp] view plain copyprivate List<BaseInputModule> m_SystemInputModules = new List<BaseInputModule>();  private BaseInputModule m_CurrentInputModule;  

系统输入模块表和当前输入模块。

BaseInputModule是一个抽象类,PointerInputModule继承自它,同样也是抽象类,而StandaloneInputModule和TouchInputModule又继承自PointerInputModule。StandaloneInputModule是面向“PC, Mac& Linux Standalone”这个平台的输入模块,而TouchInputModule是面向“iOS”、“Android”等可触摸移动平台的输入模块。

EventSystem会每一帧都处理这些输入模块,首先是调用TickModules方法,更新每一个InputModule。

然后遍历m_SystemInputModules判断这些module是否支持当前的平台(例如StandaloneInputModule需要判断是否鼠标已连接,而TouchInputModule需要判断是否支持触摸)且module是否可激活(可激活条件祥参StandaloneInputModule和TouchInputModule的源码)。

如果有符合条件的module便赋值给m_CurrentInputModule(当前输入模块)并break。

如果没有符合条件的module便选取第一个支持当前平台的module作为m_CurrentInputModule。

最后如果m_CurrentInputModule的值变化了并且m_CurrentInputModule不为null便调用:

而这个方法会将各种输入事件(如点击、拖拽等事件)传递给EventSystem当前选中的GameObject(m_CurrentSelected)。

[csharp] view plain copym_CurrentInputModule.Process();  

而m_CurrentSelected大部分情况是Selectable组件(继承自它的有Button、Dropdown、InputField等组件)设置的,相关代码我们会在后续的文章中介绍。

而设置m_CurrentSelected的时候,会通过ExecuteEvents这个类对之前的对象执行一个被取消事件,且对新选中的对象执行一个被选中事件。这就是OnSelect和OnDeselect两个方法的由来。

EventSystem的RaycastAll方法使用射线从相机到某个点(设为点E)照射在UI上,然后对被照射到的所有对象进行排序,大致是远近排序。

而这个方法实在PointerInputModule中使用的,如果点击(或触摸)事件移动的时候,被该事件影响的对象也会发生变化,通过RaycastAll方法(传入的eventData中的position属性作为点E)获得到第一个被射线照射到的对象,如果与之前的对象不同,便变更对象(同时会回调原对象的OnPointerExit和新对象的OnPointerEnter方法)。

IsPointerOverGameObject是EventSystem类里特别常用的一个方法,用于判断是否点击在UI上,具体是在PointerInputModule中实现的,以后我们研究UGUI的输入模块的时候会深入讲解,概括一下就是判断当前是否存在某个键位(默认是-1鼠标左键)的数据。

最后我们注意到EventSystem有一个static属性:

[csharp] view plain copypublic static EventSystem current { get; set; }  

因为是静态属性,所以只存在一个current,而并不会每个实例对象会有一个.

当一个EventSystem组件OnEnable的时候会将这个对象赋值给current。参考OnEnabled与OnDisabled。

[csharp] view plain copyprotected override void OnEnable()  {  base.OnEnable();  if (EventSystem.current == null)  EventSystem.current = this;
#if UNITY_EDITOR  else  {  Debug.LogWarning("Multiple EventSystems in scene... this is not supported");  }
#endif  }  

OnDisable的时候会将current赋值为null(当current==this)。参考OnEnabled与OnDisabled。

[csharp] view plain copyprotected override void OnDisable()
{  if (m_CurrentInputModule != null)  {  m_CurrentInputModule.DeactivateModule();  m_CurrentInputModule = null;  }  if (EventSystem.current == this)  EventSystem.current = null;  base.OnDisable();
}  

这就是为什么我们在Unity Editor里面增加多个EventSystem的时候会报警告。

当然在游戏运行的时候,我们也不能随意的增加删除EventSystem,一来似乎并没有什么必要,二来虽然EventSystem本身并没有太多东西,但是毕竟输入模块里面还是保存了一些数据的。

转载于:https://my.oschina.net/u/2874878/blog/1594641

UGUI内核大探究(一)EventSystem相关推荐

  1. UGUI内核大探究(十六)InputField

    InputField是UGUI的重要组件,可以提供文本输入功能,是与用户交互的一个重要手段.我们可以在编辑器里,为OnValueChanged和OnEndEdit两个事件添加监听,这样就可以获得用户输 ...

  2. UGUI内核大探究(十八)Raycaster

    射线其实是属于事件系统,它在EventSystem/Raycasters目录下,有BaseRaycaster.PhysicsRaycaster和Physics2DRaycaster三个类,命名空间也是 ...

  3. UGUI内核大探究(十三)Dropdown

    Dropdown(下拉框)可谓是UGUI的集大成者,在Unity Editor里新建一个Dropdown,会随之附赠Text(Label对象).Image(Arrow对象).ScrollRect(Te ...

  4. UGUI内核大探究(二)执行事件

    UGUI内核大探究(一)EventSystem我们探究了事件系统,其中我们讲到EventSystem可以通过ExecuteEvents这个类来执行事件,那么事件是如何执行的呢?这里涉及到了两个文件Ev ...

  5. UGUI内核大探究(九)Image与RawImage

    Image组件是UGUI里最常用的组件(可能没有之一),我们知道其实还有一个RawImage组件.那么二者的区别是什么呢?之前的文章UGUI内核大探究(八)MaskableGraphic中我们提到过, ...

  6. UGUI内核大探究(八)MaskableGraphic

    MaskableGraphic是UGUI的核心组件,它继承自Graphic.MaskableGraphic是一个抽象类,它的派生类有RawImage.Image.Text.顾名思义,MaskableG ...

  7. UGUI内核大探究(十二)Slider

    Slider是UGUI的一个组件,使用它可以实现滑动条,算是一个比较常用的组件,它与ScrollBar(参考UGUI内核大探究(十一)ScrollRect与ScrollBar)有些类似,但又不太相同. ...

  8. UGUI内核大探究(十一)ScrollRect与ScrollBar

    当我们在Unity Editor里创建一个Scroll View的时候含有ScrollRect的对象,它下面还有三个子对象,两个含有ScrollBar组件的子对象是作为滚动条,一个Viewport用于 ...

  9. OS内核(xv6)探究-系统调用

    内核态和用户态 计算机在加载操作系统之后,再继续执行任何指令的时候,都会处在某种特权级下(privilege).例如在Linux下,可能会有ring0,ring1,ring2,ring3等几种状态,这 ...

最新文章

  1. Android高仿IOS和QQ的弹出对话框
  2. JAX-WS开发webservice示例详解
  3. oracle tovarchar2_oracle数据库中varchar2陷阱
  4. 自动生成四则运算题目
  5. CAN笔记(9) 位填充
  6. 跨平台最好用笔记软件——Simplenote
  7. 腾讯发力研发文化升级,宣布加入Linux基金会TODO 工作组
  8. 使用FusionChartsFree整合项目
  9. 3DS MAX 批量导出文件脚本 MAXScript 带界面
  10. python123平台怎么上课_国内优秀的Python教学平台推荐-python123.io
  11. Python实现m3u8下载mp4视频原理及源码
  12. R语言第四次作业(股票、债券收益率计算)
  13. 图论介绍和PyTorch Geometric(PyG)库基础知识
  14. 如何解决Invalid quadratic form: product is complex
  15. element-ui前端页面消息提示框
  16. 最强神作 Crysis深度剖析与优化指南
  17. java二进制算法教程_关于JAVA入门二进制课程的笔记
  18. python爬虫实战,爬虫之路,永无止境
  19. 疫情严峻,为什么VR全景能逆生长?
  20. 卓朗数字孪生的重要意义

热门文章

  1. C语言输入一个任意数求各位数的和
  2. STM32串口中断的4种接收数据的实现方式
  3. 如何屏蔽VS2013中的4996错误!
  4. .net引用System.Data.SQLite操作SQLite
  5. printf 命令详解
  6. mysql cmd终端服务无法启动
  7. getOwnPropertyNames() keys()
  8. RHEL6.3配置文件共享(5) Samba服务之三
  9. Elasticearch 安装 基础介绍 (一)
  10. C语言 标识符的作用域