很多Unity3D项目都使用了UGUI,但并不是所有人都研究过它的内部结构。由于准备定制自己的UI,不弄明白它内部的机制有点说不过去呢。这篇文章主要分析一下它的事件体系结构,以及点击事件的逻辑流程。本篇文章依托于UGUI的源码。
事件体系
事件体系总体上说由四部分组成,分别是:监测器,派发器,采集器,响应器。
监测器指的是EventSystem类,它重写了MonoBehavior的Update方法,会在每一帧更新挂载在同一个GameObject上的BaseInputModule组件状态,并判断是否应该激活Module,如果是,则去调用各个Module的Process。
派发器指的就是BaseInputModule,最常用的是它的子类StandaloneInputMoudle。它完成了实际的事件生成。包括且不限于:事件类型的确定,事件数据的收集,派发对象的过滤。其中对派发对象的获取需要借助采集器,但需要通过监测器来获取,这种设计可以带来效率上的优势,虽然实现时并没有相关的代码。
采集器是指BaseRaycaster,在UGUI中使用的是其子类GraphicRaycaster。当事件发生时,会由Module请求一个射线点触,返回所有能点到的物体并返回,交由派发器进行过滤。它有一个内部的管理类RaycasterManager,用来做链接采集器和监测器的单向桥梁。
响应器是指IEventSystemHandler及其子类,例如最常用的IPointerClickHandler,它处理的是点击事件。通过ExecuteEvents类,可以将发生事件的对象上所有的响应器都获取到并调用其响应逻辑。以点击为例,事件最终会被派发到OnClick的代理上。完成逻辑的执行。
这四个模块大致的依赖关系如下:
类图
类有好多,但相比于流程要简单不少。类分两部分,一部分是功能类,一部分是编辑器类。
功能类按照上一节的事件体系可以清晰的找到重要的基类,UML图如下:
这个图只是和点击相关的部分,当然还有很多其他的功能例如拖拽,滑动等等。但如果能找到这些重点,其他分支逻辑相信大家分分钟都能看懂了。
另一类是编辑器类,这个比较简单,我就没单独梳理类图,直接用VS自动生成的类图就够用了:
你若是觉得这些编辑器类没什么用,那你一定是对编辑器代码理解还不深。UGUI的编辑器界面还算获得了广泛的好评,当需要自定义Inspector界面时,一些功能一定用得上,如果有空我也准备深入研究一下。
点击的逻辑流程
下面基于事件体系的划分,针对一次按钮点击梳理一下调用逻辑,流程图如下:
“动手改之前,要先弄明白别人的程序逻辑”。说起来很简单,但又有几个人能坚持做好呢?虽然我也是在外层包装了各种控件之后,才下决心重写UGUI 。 看到现在这种程度可真心花了不少时间,整理出来希望对大家有帮助