提交 5f346b8b 编写于 作者: kerven_hankangwen's avatar kerven_hankangwen

更新README.md

上级 2627d45b
......@@ -306,7 +306,9 @@ public void RaycastAll(PointerEventData eventData, List<RaycastResult> raycastRe
它首先获取所有的BaseRaycast对象,然后调用它的Raycast方法,用以获取屏幕某个点下的所有目标(这个方法具体功能及实现的会在Raycast模块中进行讲解),最后对得到的结果进行排序,大部分情况都是根据深度(Depth)进行排序,在一些情况下也会使用距离(Distance)、排序顺序(SortingOrder,如果是UI元素则是根据Canvas面板的Sort order值,3D物体默认是0)或者排序层级(Sorting Layer)等作为排序依据。
讲了这么一大堆,来张图总结一下。EventSystem会在Update中调用输入模块的Process方法来处理输入消息,PointerInputModule会调用EventSystem中的RaycastAll方法进行射线检测,RaycastAll又会调用BastRaycaster的Raycast方法执行具体的射线检测操作,主要是获取被选中的目标信息。
![在这里插入图片描述](https://img-blog.csdnimg.cn/fb6d708a56224ffdad54476de2e52afa.png)
简单概括一下UML图的含义,比如实线+三角形表示继承,实线+箭头表示关联,虚线+箭头表示依赖,关联和依赖的区别主要是引用其他类作为成员变量代表的是关联关系,将其他类作为局部变量、方法参数,或者引用它的静态方法,就属于依赖关系。
InputModules
输入模块是配置和定制事件系统主逻辑的地方。 自带的输入模块有两个,一个是为独立输入(StandaloneInputModule),另一个是为触摸输入(TouchInputModule)。 StandaloneInputModule是PC、Mac&Linux上的具体实现,而TouchInputModule是IOS、Android等移动平台上的具体实现,每个模块都按照给定配置接收和分派事件。 运行EventSystem后,它会查看附加了哪些输入模块,并将事件传递给特定的模块。 内置的输入模块旨在支持常见的游戏配置,如触摸输入、控制器输入、键盘输入和鼠标输入等。
......@@ -336,7 +338,9 @@ InputModules
执行事件
既然InputModule主要就是处理设备输入,发送事件到场景对象,那这些事件是怎么执行的呢?在讲Button的时候,我们提到过ExecuteEvent类,其实事件的执行都是通过这个类进行的,不过也需要EventInterface接口配合。这个类中定义了许多接口,比如鼠标按下、点击、拖拽等,下图展示了部分接口的继承关系。
![在这里插入图片描述](https://img-blog.csdnimg.cn/d39029d381724c579603a51f9d30b679.png)
ExecuteEvent类中提供了一个方法让外部统一调用以执行事件
```csharp
......@@ -420,7 +424,9 @@ public static GameObject GetEventHandler<T>(GameObject root) where T : IEventSys
Graphic Raycaster: 检测UI元素
Physics 2D Raycaster: 用于2D物理元素
Physics Raycaster: 用于3D物理元素
![在这里插入图片描述](https://img-blog.csdnimg.cn/0e44f4ec54dd4e84804ae91338c28157.png)
BaseRaycaster是其他Raycaster的基类,这是是一个抽象类。在它OnEnable里将自己注册到RaycasterManager,并在OnDisable的时候从后者移除。
RaycasterManager是一个静态类,维护了一个BaseRaycaster类型的List,功能比较简单,包含获取(Get)、添加(Add)、移除(Remove)方法。
......@@ -475,6 +481,7 @@ Physics2DRaycaster继承自PhysicsRaycaster,实现功能和方式基本一致
### GraphicRaycast
GraphicRaycast用于检测UI元素,它依赖于Canvas,我们在场景中添加Canvas默认都会包含一个GraphicRaycast组件。它先获取鼠标坐标,将其转换为Camera的视角坐标,然后分情况计算射线的距离(hitDistance),调用Graphic的Raycast方法来获取鼠标点下方的元素,最后将满足条件的结果添加到resultAppendList中。
![在这里插入图片描述](https://img-blog.csdnimg.cn/075dc249a77944e4b4b7664db687a790.png)
```csharp
......@@ -675,6 +682,7 @@ private static void Raycast(Canvas canvas, Camera eventCamera, Vector2 pointerPo
}
```
函数中又调用了Graphic类的Raycast函数,它主要是做两件事,一件是使用RectTransform的值过滤元素,另一件是使用Raycast函数确定射线击中的元素。RawImage、Image和Text都间接继承自Graphic。
![在这里插入图片描述](https://img-blog.csdnimg.cn/5d3603d2ab3d4fbbaab22e01fdea6cd6.png)
```csharp
......@@ -741,6 +749,7 @@ public virtual bool Raycast(Vector2 sp, Camera eventCamera)
}
```
这里也使用了ICanvasRaycastFilter接口中的IsRaycastLocationValid函数,主要还是判断点的位置是否有效,不过这里使用了Alpha测试。Image、Mask以及RectMask2D都继承了该接口。
![在这里插入图片描述](https://img-blog.csdnimg.cn/a05d890cd73e4e5fb0b7dc991d990f16.png)
```csharp
......@@ -787,6 +796,7 @@ public virtual bool IsRaycastLocationValid(Vector2 screenPoint, Camera eventCame
```
### EventData
EventData用以存储事件信息,涉及到的东西不多,不展开讲解,层级关系如下图所示
![在这里插入图片描述](https://img-blog.csdnimg.cn/416a223095af40aaaab754b2e26f0b9d.png)
### 实战:为Button的点击事件添加参数
在执行Button点击事件时,有些情况下我们需要获取触发事件的Button对象信息,这时可以自己实现一个Button点击事件
......@@ -844,8 +854,11 @@ public class UIEventListener : MonoBehaviour, IPointerClickHandler, IPointerDown
使用的时候,我们只需要将它挂载到Button组件上,然后在PointerClick事件中添加自己的处理函数。
### 总结
utton点击事件怎么触发的呢?首先是EventSystem在Update中调用当前输入模块的Process方法处理所有的鼠标事件,并且输入模块会调用RaycastAll来得到目标信息,通过冒泡的方式找到事件实际接收者并执行点击事件(这只是总体流程,中间省略很多具体步骤)。
![在这里插入图片描述](https://img-blog.csdnimg.cn/44c8538525d14bb2b6cdbdf9a31bd099.png)
最后来一张层级关系图
![在这里插入图片描述](https://img-blog.csdnimg.cn/0cb7a4ba7fa345078c7f404acf6d30c3.png)
</details>
......@@ -856,7 +869,9 @@ utton点击事件怎么触发的呢?首先是EventSystem在Update中调用当
首先我们需要明白一个问题:Unity是怎么绘制UI元素的?
Unity中渲染的物体都是由网格(Mesh)构成的,而网格的绘制单元是图元(点、线、三角面)。在unity中添加一个Image和Text,并且将Shadings Mode设置为Wireframe模式,可以看到一个Image由四个顶点和两个三角面构成,Text也是由许多顶点和三角面构成。
![在这里插入图片描述](https://img-blog.csdnimg.cn/4c59fa44bc684b1aa0fd5c2b0c10c1e1.png)
绘制信息都存储在Vertexhelper类中,除了顶点外,还包括法线、UV、颜色、切线以及一些函数,下面是它的部分代码
```csharp
......@@ -897,9 +912,13 @@ public class VertexHelper : IDisposable
数据存储好了,那怎么绘制呢?
这是依靠CanvasRenderer来完成的,它听起来可能比较陌生,但实际上当我们在项目中创建的一些UI元素,比如Button、Image、Text时,都包含组件CanvasRenderer,这个类提供了许多关键绘制信息,比如被渲染物体的颜色、材质和Mesh等,主要作用就是渲染包含在Canvas中的UI对象,但是在Inspector界面中并不会展示任何属性。
![在这里插入图片描述](https://img-blog.csdnimg.cn/5974159c8e8646f89fe5733c1c460524.png)
下面列出了几个比较重要的属性和方法,详情见Unity Documentation: CanvasRenderer。
![在这里插入图片描述](https://img-blog.csdnimg.cn/a1f0200c340a44c5b134f1709d3b18d6.png)
总结一下就是Unity会把要绘制的UI信息保存在Vertexhelper中,并且调用CanvasRenderer里面的方法进行绘制,具体的绘制时机,就是今天的重点内容了。
这是UGUI源码系列的第二篇内容,如果没有任何基础,可以先看看文章 UGUI源码入门。
......@@ -908,11 +927,15 @@ public class VertexHelper : IDisposable
UI重建分为两类,一类是布局重建(Layout Rebuild),另一类是图形重建(Graphic Rebuild)。
一个UI若要重建,必须继承自ICanvasElement接口,因为执行重建操作的时候会调用接口中的Rebuild函数。CanvasUpdateRegistry类监听了Canvas的willRenderCanvases事件,该事件会每帧调用并执行PerformUpdate函数。PerformUpdate被调用时会遍历RebuildQueue中需要进行重建的UI元素,并调用元素的Rebuild方法。
![在这里插入图片描述](https://img-blog.csdnimg.cn/75a9da05abde4eb696b193a5146714bd.png)
下面对这些步骤展开详细的讲解。
### ICanvasElement
首先是ICanvasElement接口,重建的时候会调用它的Rebuild方法,继承它的类都会对这个函数进行重写,Unity中几乎所有的UI组件都继承自这个接口。
![在这里插入图片描述](https://img-blog.csdnimg.cn/ca9b3653d0f04aaa99d3c6e54464561c.png)
下面是接口中包含的方法。
```csharp
......@@ -1091,6 +1114,7 @@ private bool InternalRegisterCanvasElementForGraphicRebuild(ICanvasElement eleme
以Graphic为例,我们看一下什么时候会向重建队列中添加元素。
### Graphic
![在这里插入图片描述](https://img-blog.csdnimg.cn/b00c3c9fa6fe4bd1a8fcaad8df1c39ce.png)
以Graphic为例(Image和Text间接继承自它),看一下具体发生了什么。
首先是将自身加入重建队列,这里是通过设置“脏数据”实现的,包括布局(Layout)、材质(Material)和顶点(Vertices)三部分,设置布局为脏,将进行布局重建,设置顶点或材质为脏,则进行图形重建。布局重建会将自身加入m_LayoutRebuildQueue中,图形重建则会将自身加入m_GraphicRebuildQueue中,等待被调用。
......@@ -1273,7 +1297,9 @@ public override void SetNativeSize()
}
```
即对应下图中的SetNativeSize按钮
![在这里插入图片描述](https://img-blog.csdnimg.cn/aec02e30650e41de9d59704ac0fd80c7.png)
当然修改Image其他的属性也可能会引发重建,调用的地方太多了,想要进一步了解的同学可以在源码中找到答案。
Text类似,当文本的字体、大小等属性发生变化时,也会引起重建。
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册