被NGUI折磨中的攻略心得
到新公司负责NGUI的工作,在目前几乎没有他人的帮助下,只得一边摸索一边完成工作。现将遇到的问题记录下来,一是加深自己的印象,二是也许能帮到其他学习者,毕竟目前网上NGUI相关系统的教程太少了。
(所使用的NGUI版本是3.7.0以上)
分享下获取过来的英文教程,此教程使用的NGUI版本虽然比较旧,但主要功能都有较好介绍,老外甚至用NGUI做了一个简单的小游戏~~
http://pan.baidu.com/s/1pKf88iB

Problem 1:U3D初始开启了默认的天空,曾找了半天找不到哪里可关闭和更换,其实打开Window-Lighting中即可设置。
problem2:在摆UI时,开始没有注意各个节点的坐标,导致设计视窗和运行视窗中看到的结果不一样,其实是节点Z轴没有统一。所以要么就用2d模式,节省调节坐标,要么就要把各节点坐标调好。在Hierarchy中,资源可看做以节点的方式组织,结构关系十分像程序中的父类和子类。当在一个名叫Wnd的panel父节点下放置其它如Sprite的子节点,那么子节点就继承了父节点的坐标系,子节点的坐标就变成了相对坐标。

problem3:用NGUI的atlas maker和Font maker制作bmpFont和图片混合的图集时,遇到过图上问题,报错且一直updating,是说图集中部分内容被挤出去了,生成失败。一个原因是时,没有勾remove empty选项,导致空白占用了过多空间(而且似乎一张文字图集达到2048*2048的尺寸时就容易报错)。还有一个原因尚不清楚,即使勾选了remove empty选项照样报错。这样我的做法是,先把图片生成一个图集,再选取生成好的bmpFont,右键打开图集管理,点击update到这个图集中,然后还要注意把Font的字符定位文件xx.txt再次导入到整个图集的预制中,完后之前Font的材质球则可删除。

problem4:点击选取的节点,ctrl+6打开动画编辑面板,做好一段动画后顺利地播放,然后在其子节点再ctrl+6编辑动画,播放......结果发现把先前做的动画覆盖了。只要稍微注意就好,因为子节点默认是有父节点动画的,子节点要自己挂上一个animation或animator组件,才可做自己的动画。

problem5:在制作动画的时候,需要做一个移动+透明度渐变的过程。之前在节点属性上挂着NGUI Tween系列的Tween Alpha脚本,然后在动画面板上引用。播放结果是正确的,但是在实时游戏中,Tween Alpha只能作用一次。原因是Tween系列脚本不能通过动画反复播放,似乎是动画不会重置Tween?它单独挂在节点上是可以反复的。因此把Tween Alpha脚本替换为Animation Alpha就ok了。

problem6: 在使用table的时候,给table下的其它子节点增加了一个tween scale这种改变table元素位置的脚本,结果子对象发生了偏移,破坏了原有的对齐。原因是table下的所有子节点需要初始保持坐标一致,然后直接通过table的alignment或者spacing x/y等等设置来修改,不要手动一个个来调节,否则容易发生不可测的变动。(后来发现,table中子节点如果被隐藏,而又勾选了Hide Inactive选项,会导致对齐发生偏斜)。

problem7:NGUI的toggle组件。这个组件也和什么label,button等等一样,只需挂在一个gameobject上,调整参数就ok。最重要的修改,是toggle的Group、State of 'None',以及Starting State三项,其余的按默认设置是ok的。
*Group:表示当前UI中,会把group相等的toggle关联起来,使其互斥。
*State of 'None':表示点击toggle本身,也可在checkmark和background中进行切换。
*Starting State:表示该toggle是本界面中默认被选取的,通常仅有一个toggle会被勾上。

problem8:通过Tween Scale和Play Tween来配合,使点击某个gameobject就可下滑出隐藏对象的尺寸变化动画。Trigger condition 原是On Click,Play direction设置为toggle,但需要使若干个目标进行互斥,这样设置是不行的。而把触发事件改成On Select便可使其互斥,但是会有bug,多点几次就会发现这些对象变得乱七八糟。 后来把play direction改为forward 就ok了。但整体效果还是不够好,所以点击按钮拉出下滑条的效果,要么用动画做,要么写脚本。
problem9:NGUI的根节点,UIRoot将把子节点的Scale强制设置为1,这样无法将UI组件整体大小自由调节,后来发现只需改变子节点中的子节点即可。UIRoot是要控制屏幕自适应的,所以手动不能更改。
problem10:对新手来说,项目保存会一时纠结不清。在场景中创预制,是需要将预制做完后要手动拖入project中。并且U3D中包括预制,有三种保存方式,分别是save scene,save project,以及预制上的apply。save scene是保存当前场景状态;project则是整个工程,而预制的话必须点击inspector面板上的apply来保存更改。有时将预制拖入其它预制中,做了更改,点击apply会发现该预制没有被保存,只得重新拖入project中覆盖掉之前的。

problem11:FBX模型的使用,导入FBX格式模型至project中,然后可以像prefab一样使用,但是这种方法用在UI上会比较耗性能,因为模型通常开销大,且质量越高越甚。Ctrl+6可以看到Animation下的模型动画设置,非常复杂,不过不需要自己手动调,因为这些都是从相关3D软件中读取出来的。

problem12:Window-Aniamtor打开animator的设置界面,可以在试图中创建动画块,以及连接动画块来确定多个动画之间的转换逻辑关系。本动画系统比老动画系统更加高级,但实际上手亦不难,只需自己多动手足可。

problem13:父节点挂着boxcollide导致的子节点收不到事件响应。因为每个panel都有自己的层级,不同的panel间是无法点击穿透的。如果一个panel是用做二级界面弹出框,它自带一个全屏的boxcollide,则可防止点击穿透到其下面panel的UI上。另外如果在一个scroll view组件中,如果在scroll view的panel上挂了drag scroll view组件来响应滑屏效果,那么其下面挂着的子节点上无法再挂drag scroll view组件,会有冲突(目前最好的做法,是在下面子节点上挂drag scroll view,然后调整布局,使其滑动顺畅)。

problem14:Panel上Clipping的诡异问题,刚接触Scroll View组件弄出的问题,一般来说应该遇不到。如图左侧Sprite超出裁剪区域一半了,却没被裁剪,只有全部超出才被裁剪。这个问题纠结很久,后来才发现其实是shader的问题。NGUI自带了很多shader,其中有一系列shader(Transparent colored 1、2、3,Transparent colored(TextureClip)......)是负责透明像素的处理,而panel的裁剪则是运用了这些shader,图上问题正是个别shader丢失导致的。

problem15:逗逼的AtlasMaker对话框,如果要大量通过点取删除单个精灵,那么一不小心点在Scene视图上则所有选取消失(其它的地方貌似ok,貌似是个bug),因此不要尝试一次性全点完后作删除。

problem16:多个tween系列的动作,无论是挂在一个gameobject上,还是多个,如果需要让这些动作连续,在Inspector编辑面板上貌似只能通过Start Delay方式来实现。

problem17:button和sprite同时挂载一个gameobject上,会有bug,导致功能异常。一般Sprite放到Button下。


problem18:一般来说,ScrollView的参数不需要手动更改,除了Movement和Cancel Drag If Fits。它们一个是控制垂直还是水平滑动,一个是控制但ScrollView的panel显示区域中,子对象没有超出该区域时,不让其拖动,不勾选则反之。然而有时就放一个子对象进去,也能滑动,其原因要注意子对象身上的各种ui元素,是否超出了区域,可看到UI周围的黄线,就是代表UI中的widget实际所占的一个区域大小。

problem19:关于UI性能消耗问题,可以在做UI时,打开states查看相关的Batches(即为DrawCall,每帧UI需要被底层directX绘制多少次),以及更详细的打开Window/Frame Debugger来追踪。Drawcall消耗问题,之前听说单个widget的depth不同,将引发额外的DC,实际上并不是这样,而是引用了不同图集,然后再设置depth这种影响渲染优先级的操作,就将导致取相同图集中的Sprite也会额外多出一个DC,如图sundryAtalas用了两次DC。

一个好习惯:在摆UI时,先保存一份公共的模板,然后通通Copy and paste过去,这样既轻松,又避免了手动调整带来的误差。

另外在使用各种NGUI组件时,可以通过它提供的模板工具来做,只需选择预设好的模板,点击一下就创建出了对象。十分方便,而且也避免了手动去统一调整。本人之前不知道有prefab toolbar,一直用的legacy widget tool。而新的prefab toolbar更好,可存储自己做的一个模板,然后用的时候copy出来,推荐使用这个。

UIButton的系列组件,目前我用的最多的是Button、Button scale。其余的之前都被我无视了,其实有一些都很不错的,如Button Activate,可以控制一个GameObject的显/隐,Button drag 可以控制一个scroll view的点击滑动,Button Rotation可以使按钮增加旋转效果。

NGUI组件上系列回调接口,如图的On Click,可以自己编写一个函数,然后直接挂上去,NGUI组件会自动根据条件来执行。这其实是非常不错的一个功能,虽然多半是程序的事,但作为策划,或者UI设计人员,可以让程序写完一些功能,然后自己挂上去。