unity3D游戏开发十四之NGUI一
转:http://blog.csdn.net/kuloveyouwei/article/details/23676039
在Unity中,可以使用代码控制其自身所携带的GUI来实现图形界面的搭建。但是这些组件的搭建效率很低,而且已经无法满足现在市场对图形用户界面美感的要求,所以,引入了NGUI来增加所要开发的图形用户界面的美感。NGUI是一个功能强大的UI系统,其事件处理通常由开发人员编写C#脚本完成,并且是一个严格遵循KISS原则的Unity框架,该框架具有干净、简约的代码。
现在NGUI的各个版本很多,我这里用的是3.0.6版本,导入NGUI包,成功后,会在菜单栏中显示NGUI选项,如下图:
依次打开菜单栏,NGUI->Open->UI Wizard选项,如下图:
点击Layer下拉列表,选择Add Layer,创建一个叫NGUI的层,如下图:
Camera选项中有3个选项,None,Simple2D,Advanced3D,Simple2D新建一个简单的2D界面,没有Z轴效果,Advanced3D新建一个3D界面,有Z轴效果,并且可以3D旋转。我们点击Create Your UI按钮,创建一个UI界面,程序会自动为我们创建一个有节点层级关系的一些物体,分别是UI根节点,,一个相机节点,一个锚点节点,和一个用于盛放按钮等UI的Panel节点我们现在可以不用管这些节点的功能和作用,只要记住Panel节点即可,以后我们创建的所有按钮等UI都放在Panel层级下,如下图:
我们先来看看UIRoot,UIRoot总是放在NGUI UI层级的最上层。它用来使UI的缩放变得更容易。widget通常使用的是以像素为单位的坐标,但是一个800*400(dimensions的值)的widget会占用800*400个单位(Unity中的单位),这相当大。UIRoot通过屏幕高度的反比来进行缩放,因此widgets都会很小,并且操作起来更容易。属性如下图:
其中,Scaling Style(缩放类型,包含三种),UIRoot有几种缩放方式。最常见的就是PixelPerfect。这种方式下,你的UI一直都是以像素为基础,一个300*200的widget在屏幕上永远占用300*200像素。这就意味着,你的UI在低分辨率的机器上会显得非常大,在高分辨率的机器上就会显得很小。这个设置就是一直保持你的UI清晰。FixedSize是一个和它功能正好相反的设置。当UIRoot用了这个选项,你的屏幕永远都会保持NGUI所关心的尺寸,不管你的实际屏幕是多大。就是说一个300*200的widget占用了1920*1080的25%的屏幕,那么当分辨率降低到1280*720的时候,它同样占用25%的屏幕。如果你不介意你的UI看起来像是不同的尺寸,也不关心是否清晰(就是可能一个小的UI被拉伸很大),那么选择这个选项。选择它的时候,不要忘记设置Manual Height。 FixedSizeOnMobile是前两种的组合。选择这个选项后,会在pc或者mac等桌面设备上用“PixelPerfect”,在移动设备上用“FixedSize”。 如果你没有选择Fixed Size选项,那就要设置Minimum和Maximum Height的值。这些值让你的虚拟屏幕看起来在合理范围。比如选择了Pixel Perfect方式,Minimum Height设置为720,那么当有玩家把你的程序运行在800*600(高度是600,小于Minimun Height)的设备上时,你UI的行为就和设置了“Fixed Size”模式、Manual Height值设为720的时候一样。
接下来我们看下UICamera,属性如下图:
UICamera真正做的事情是发送NGUI事件给所有被当前camera渲染的object,camera是UICamera脚本所在的那个。 其实这个脚本做的事情和UI无关。事实上如果你想让游戏里面的object接收OnPress、OnClick、OnDrag等这类事件,你需要把UICamera挂在你的主相机上。游戏场景里面可以有多个UICamera。大多数游戏一个挂在渲染widget的相机上,一个挂在渲染游戏的相机上。
UICamera的选项Event Type用来决定脚本如何排序mouse或者touch触发的事件。如果是UI模式,这些事件顺序基于widget的depth——和渲染顺序一样。如果UICamera挂到了Main Camera上,那么就需要把这个选项修改成World模式。这样就会根据与相机的距离来排序点击到的object。
Event Mask用来决定哪些层会接收事件。大多数情况下你需要的就是“Everything”,这个值会与UnityEngine.Camera's Culling Mask进行逻辑与运算,有需要的话你可以微调这个值。如果你修改了UI的game object的Layer,记得调整Event Mask,否则你可能会发现UI不响应事件。
Debug选项用来显示当前在鼠标下面的是什么。如果你不知道是什么东西接收了鼠标事件,勾选上这个选项你就可以在右上角看到了。
Allow Multi-Touch选项用来控制是否支持多点触碰。如果勾选掉,多点触碰也会当做单点触碰。
Sticky Tooltip选项用来微调tooltip的行为。如果关掉,当鼠标再次移动的时候就会立即关掉tooltip。如果打开,只要鼠标一直在这个game object上,tooltip就会移至显示。
Tooltip Delay用来控制当鼠标停在某个object上时,经过多长时间OnTooltip消息会被发送到这个object上。以秒为单位。
Raycast Range控制raycast的长度,大多数情况下这个值可以被忽略。这个值是世界坐标系的值,所以如果你的摄像机的near clip是0.3、far clipping是 1000,比较远的物体可能不会响应click事件,比如可以把这个值设置为2000(比far和near clipping大的值。)
Event Sources用来确定哪些事件类型会被处理。被勾选掉的事件就不会被处理。有些平台会强制关闭一些事件。比如使用手柄时会自动关掉鼠标和touch时事件。
Thresholds可以调整click、drag和tap事件的阈值来微调鼠标和touch事件的行为。以像素为单位。
Axes和Keys部分用来控制哪个轴控制哪个方向的移动。这些名字需要和Input Manager里面的一致。
UIAnchor,属性如下图:
UIAnchor让你可以固定game objects在屏幕或者其他widgets的某一边或者某一个角。这是一个关键的组件,用来在NGUI中创建模块化的UI。
是否想让你的一部分UI粘在屏幕的角落或者边缘上?比如魔兽世界。在这个游戏中,游戏地图永远在屏幕的右上角,热键一直在屏幕的下方,不管你用的是多大的屏幕分辨率。你如何做到类似的东西呢?用anchors。
NGUI的默认UI布局会给你提供一个anchor——一个居中的anchor。以魔兽世界的UI为例子,你需要增加额外的两个anchor。一个设置成TopRight,另一个则为Bottom。之后你给这两个anchor增加一些子节点,然后修改屏幕的尺寸,你会发现UI会一直在你想要的地方(右上方或者下面)。
通过设置anchor的Container让一个UI附着在另一个UI上。如果Container是UIWidget,那么会用widget的dimesions来代替屏幕矩形(就是TopRight将将是相对与这个widget,而不是屏幕)。如果是game object,那么这个矩形就是game object下的所有节点widget的bounds。因为这个原因,当你用父节点当做Container的时候一定要注意,因为父节点的Container大小会包含这个你要anchor的widget,这可能不是你要的效果(比如你要放在父节点的左上角,但是当这个widget到了左上角后,父节点的左上角由于这个widget的到来可能就变了,之后再次移动widget,周而复始……)。
调整Relative Offset来用相对值来改变位置。 如果X是1就是100%的container宽度. Y是1就是100%的container高度。 0.5 = 50%,等等。也可以是负数。
上面的调整也可以通过用Pixel Offset来实现。就和你想的差不多……通过给定的X、Y的值来以像素为单位调整anchor的偏移。
默认情况下anchor只会执行一次。如果要在每个update里面都执行,那勾选掉Run Only Once选项。
UIWidget,属性如下图:
UIWidget是NGUI的基础组件。简单来说,就是一个你可以放在屏幕任意位置的矩形框。widget会有一定的面积(如下图的白色框范围),但是在运行的时候(Game View)是完全不可见的,所以非常适合当做其他组件的容器(让所有的sprite或者label等以它进行各种对齐)。UIWidget也被用来当做所有NGUI元素的基类——所有你创建的sprites和labels。UILabel,UISprite,UITexture和UI2DSprite(Unity3D 4.3版本)都继承自UIWidget。
UIPanel,属性如下图:
UIPanel用来收集和管理它下面所有widget的组件。通过widget的geometry创建实际的draw call。没有panel所有东西都不能够被渲染出来。如果你对Unity熟悉,你可以把UIPanel当做Renderer。
所有panel都有一个Depth值,会影响所有它包含的widget。如果你的UI有很多窗口,那么最好每个窗口有一个panel。Panel上的depth权重会远远高于每一个widget的depth权重,所以保证panel不要使用同样的depth。如果使用同样的depth在panel上,那么draw call会被自动拆分来保证渲染顺序,所以会增加更多的draw call。
- Alpha属性影响所有在panel下面的widget。所以可以用它来淡出整个窗口。
- 如果你的UI需要被灯光影响,需要勾选上Normals。
- 如果创建了一个有很多geometry的scrollable panel,你需要勾选Cull选项来减少三角形的数目。这样也可能降低性能,因为widget的可视性需要每次update都检验一次。
- 勾选Static选项来告诉NGUI这个panel下面的widget不会被移动,这样可以提高性能。NGUI会忽略所有的position/rotation/scale改变。所以在运行时移动widget不会有效——所以小心使用。
- 如果要调试由panel创建的draw calls,Show All选项可能帮助到你。你会看到由panel创建的所有draw call,以渲染顺序排序。每个draw call会包括它使用到material的详细信息,那个widget用的这个material,甚至可以让你关闭某些draw call来让你查询某些问题。
Panel会根据dimensions自动Clip所有它的子节点。使用这个功能需要选择Clipping下拉列表中的任意选项,之后调整Scene View中紫色矩形的尺寸,就像调整widget的尺寸一样。通过这样做你可以把一个panel放到Scroll View中,让他轻松的拖拽。
注意clipping的panel不能嵌套。每个panel只能clip自己管理的widget,如果一个panel在另外一个panel里面,只有一个会影响到里面的widget。这个限制以后会去掉。