NGUI三大基础机制

发表于2016-10-13
评论0 9.6k浏览

  本文介绍以NGUI的版本是3.6.0版本为,主要介绍NGUI的原理,这个都是本人阅读代码得出的结论,如有错误,欢迎指定

  在NGUI有,有三大基础机制支撑整个NGUI的显示和交互,这三大基础机制分别是:渲染机制事件、消息机制、间格动画。下面将分别介绍这三个机制。

 
1、渲染机制事件
  基础介绍
  NGUIUIWidget, UIDrawCall,UIGeometry UIPanel等基础脚本
Ø  UIWidgetUI的基础组件(UILabel,UISprite)的基类,含有组件的基本信息(widthHeightcolor 锚点等)
Ø  UIGeometryUIWidget的几何数据,记录了顶点坐标,贴图的UVs和颜色等信息
Ø  UIDrawCall是将多个UIWidgetUIGeometry组合起来一起绘制
Ø  UIPanel 用于管理UIWidgetUIDrawCall等,实现界面的渲染裁剪、更新。
Ø  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就是继承于UIWeightOnFill函数实现多样的化的填装方式(即把UIWeight所需要的数据处理到UIGeometry节点中),如:拉伸、九宫格等等。

FillAllDrawCalls:全体DrawCall节点刷新。
FillDrawCall:单个DrawCall节点刷新。
  首先介绍FillDrawCall:顾名思义,这个函数是刷新单个的Drawcall节点
找到属于这个DrawCallUIWeight,然后对找到的每个UIWeight处理UV数据的组装,而这个UIWeight的数据就保存在自身的UIGeometry节点上。然后把这个Draw的数据刷新到Mesh上面去即采用UIDrawCall.UpdateGemetry
  其次是FillAllDrawCalls:顾名思义,这个函数是刷新所有的的Drawcall节点,及重建Drawcall即节点。第一步:删除已经存在的Drawcall节点。第二步:对所有的UIWeight经行排序主要按照深度值和材质。第三步:逐个顺序处理UIWeight,把相邻且具有相同的材质的UIWeightUIGeometry数据添加到同一个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");
 }
  1.  

监听和分发

  在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的继承关系图

 

               

 

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引