NGUI三大基础机制
本文介绍以NGUI的版本是3.6.0版本为,主要介绍NGUI的原理,这个都是本人阅读代码得出的结论,如有错误,欢迎指定
在NGUI有,有三大基础机制支撑整个NGUI的显示和交互,这三大基础机制分别是:渲染机制事件、消息机制、间格动画。下面将分别介绍这三个机制。
1、渲染机制事件
基础介绍
NGUI的UIWidget, UIDrawCall,UIGeometry和 UIPanel等基础脚本。
Ø UIWidget是UI的基础组件(UILabel,UISprite)的基类,含有组件的基本信息(width,Height,color 锚点等)
Ø UIGeometry是UIWidget的几何数据,记录了顶点坐标,贴图的UVs和颜色等信息
Ø UIDrawCall是将多个UIWidget的UIGeometry组合起来一起绘制
Ø UIPanel 用于管理UIWidget、UIDrawCall等,实现界面的渲染裁剪、更新。
Ø UIRoot UI界面的根目录,用于分辨率适配和事件广播。
MeshFilter 和Mesh介绍:
MeshFilter网格过滤器用于从你的资源中获取网格信息(Mesh)并将其传递到用于将其渲染到屏幕的网格渲染器当中。MeshFilter 与 Mesh 联合使用,使模型显示到屏幕上。要想在场景中看到这个网格(mesh),还需要为游戏对象(GameObject)添加一个网格渲染器(MeshRenderer),它应该是自动被添加的。但是如果你将它从你的对象中移除。你必须手动重新添加它。如果网格渲染器(MeshRenderer)不存在,这个网格仍将存在于你的场景中。但是它将不会被绘制。
NGUI的渲染机制
要详细的了解NGUI渲染机制,首先需要打开NGUI隐藏的渲染节点,秘密就在在UIDrawCall.Create(string name) 中的HideFlags.HideAndDontSave, typeof(UIDrawCall));这一行代码。打开在UIDrawCall.cs文件,打开SHOW_HIDDEN_OBJECTS宏定义。就可以看到在渲染过程中,每一个UIDrawCall对应一个把UIDrawCall作为组建的节点【在编辑器可见】如图所示:
从上面两个图就可以看出来,NGUI渲染实际上就是对通过对Mesh的渲染实现的。整个NGUI的渲染过程就把图片和文字按照一定顺序和规则组织成一系列的Mesh,然后通过Unity自身的渲染流程实现渲染。
NGUI的渲染流程
渲染过程开始的地方UIPanel.LateUpdate:在这个函数有函数调用Updateself 。
Updateself中:UpdateWidgets:更新UIWeight的位置信息、可见性[含Alpha]、UV信息,是否渲染刷新。UIsprite就是继承于UIWeight的OnFill函数实现多样的化的填装方式(即把UIWeight所需要的数据处理到UIGeometry节点中),如:拉伸、九宫格等等。
FillAllDrawCalls:全体DrawCall节点刷新。
FillDrawCall:单个DrawCall节点刷新。
首先介绍FillDrawCall:顾名思义,这个函数是刷新单个的Drawcall节点
找到属于这个DrawCall的UIWeight,然后对找到的每个UIWeight处理UV数据的组装,而这个UIWeight的数据就保存在自身的UIGeometry节点上。然后把这个Draw的数据刷新到Mesh上面去即采用UIDrawCall.UpdateGemetry。
其次是FillAllDrawCalls:顾名思义,这个函数是刷新所有的的Drawcall节点,及重建Drawcall即节点。第一步:删除已经存在的Drawcall节点。第二步:对所有的UIWeight经行排序主要按照深度值和材质。第三步:逐个顺序处理UIWeight,把相邻且具有相同的材质的UIWeight的UIGeometry数据添加到同一个UIDrawCall上来,然后把数据刷新到Mesh上。
2、消息机制
基础介绍
UICamera:真正做的事情是发送NGUI事件给所有被当前camera渲染的object,camera是UICamera脚本所在的那个。 其实这个脚本做的事情和UI无关。事实上如果你想让游戏里面的object接收OnPress、OnClick、OnDrag等这类事件,你需要把UICamera挂在你的主相机上。游戏场景里面可以有多个UICamera。大多数游戏一个挂在渲染widget的相机上,一个挂在渲染游戏的相机上。UICamera发送以下事件给collider,用他们到自己的脚本里面,只要实现相应的函数即可:
Ø OnHover (isOver) 发送时机为鼠标悬停(只触发一次)或者离开collider。
Ø OnPress (isDown) 发送时机为鼠标在collider上按下。
Ø OnSelect (selected)发送时机为鼠标点击和松开的时候都在同一个object上。
Ø OnClick ()发送时机和OnSelect一样,但是要求鼠标没有移动特别多。UICamera.currentTouchID表示按下的鼠标哪个键。
Ø OnDoubleClick ()发送时机为当在四分之一秒内click两次的时候。UICamera.currentTouchID表示按下的鼠标哪个键。
Ø OnDragStart ()发送时机为OnDrag()事件之前。
Ø OnDrag (delta) 发送时机为一个object被拖拽。
Ø OnDragOver(draggedObject)发送时机为其他的object拖拽到他的上面。
Ø OnDragOut (draggedObject)发送时机为其他的object拖拽出他的上面。
Ø OnDragEnd ()发送时机为drag事件结束。发送给被拖拽的object。
Ø OnInput (text)发送时机为输入的时候(在点击选择了一个collider之后)。
Ø OnTooltip (show) 发送时机为鼠标悬停在一个collider上一段时间没有移动。
Ø OnScroll (float delta)发送时机为鼠标滚轮滚动。
Ø OnKey (KeyCode key)发送时机为键盘或者输入控制器被使用的时候。
事件接受函数如下:
1 2 3 4 5 6 7 | void OnPress ( bool isPressed) { if (isPressed) Debug.Log( "I was pressed on!" ); else Debug.Log( "I was unpressed" ); } |
在Update()中,依次处理 触摸/点击,文本输入,键盘/摇杆输入,Tip。
其中最主要的就是 触摸/点击 事件的处理了,下面以触摸事件处理ProcessTouches()来分析。
第一步:从Input节点中,获取触摸/点击的信息为Touch类。
第二步:根据Touch类的信息,分析出可能事件。
第三步:通过物理的射线检测即(Physics.RaycastAll)找出来对应UI使用的Collider,并把Collider所在的Gameobject作为触发事件的对象。
第四步:把消息事件转化成按照实现相应的函数调用。
第五步:在控件所对应的脚本中实现对应的函数,便可以收到来自于UICamara的调用,并做相应的处理(如:UIButton)
第六部:把静态的Current变量设置为当前的控件脚本,把使用SentMessage或EventDelegate.Excute再次分发出去。如:UIToggle.OnChange
3、间隔动画Tween
基础介绍
Ø 间隔动画:对对象的某一个变量,使这个变量在一定时间段内,每一帧按照预先指定曲线变化,从而形成一段动画。如:屏幕颜色的渐变、屏幕抖动、对象的运动等等。
Ø UITweener :是实现NGUI中间隔动画的基础。间隔动画的基类,所有间隔组建都继承该类,用于执行update()。所有的继承了都需要从Begin开始。继承类中主要函数是OnUpdate,用于处理每帧的更新处理。在Begin开启后,当前脚本状态会被设为true,在运行结束之后,又会设置为false。
Ø UIPlayTween:这个脚本管理一组Tween脚本的Play,提供了不同的Tirgger,然后在不同的事件函数中触发Play(true)
UITweener的继承关系图