首先的首先,NGUI区分前后层次关系是用Depth值。已经跟z轴值无关

首先因为我自己用的是NGUI,所以我的u3d层次问题也就是NGUI的层次问题

先确定UI渲染顺序,Camera>UIPanel>Depth(UIWidget)
这里的意思是,首先确定前后关系的是不同大块之间的Camera的Depth值,根据Depth大小排列,这个决定了每个大块之前的前后关系。
接着根据UIPanel的Depth前后排序,这个是用于每个大块内可能有多个UIPanel分割成多个小块,每个小块间的前后关系。
最后是UIWidget(比如UILabel,UISprite,这些都继承于UIWidget)的Depth值,在同一个UIPanel下,决定前后关系。

这里总结来说有两个方面的问题:
1.整体的层次
2.UIPanel 间的层次

一、整体的层次:
整体的层次指的是一个游戏UI一般会分为几个模块,如Effect(特效)、Background、Main、Popup等。在这些大块之间要区分前后关系时(比如Background最后,Main中间,Popup最前)就要区分到前后层次关系。这些层次一般会有同一个父节点UI_Root(不在同一个父节点也可以)

基本上整体的层次是根据Layer来分前后关系,Layer本身是不带Depth,所以在这些大块下,一般在他们的gameobj本身或者在他们下面会有个子节点Camera。通过Camera的CullingMask来确定这个Camera具体渲染哪个Layer下的东西。而通过这个Camera的Depth值来确定整体层次间的前后关系。

注意:在大块的Camera之间如果Depth值相同时,z轴值会影响前后关系。但是这个应该是要避免的。不应该有相同Depth值得不同Camera

二、UIPanel 间的层次

网上有很多分析在不同Atlas(图集)不同depth不同z轴值时的前后关系。但是如果知道为什么就能处理所有情况。这里解释一下。

其实前后层次关系是怎么形成?是因为渲染顺序的前后关系,越晚渲染的越在前面,所有通过把一个场景分割成几块,排一下渲染顺序,按顺序渲染就能使界面正常显示而不导致遮挡错乱,这样就能控制好UI的层次关系。
而UIPanel的作用就是用来确定把什么东西放在一起渲染和UIPanel的Depth就是确定每一块的渲染顺序,最后生成一个Drawcall。
所以首先要解决的是把什么东西渲染到一块,也就是一个Drawcall里面要渲染什么,一个UIPanel里要包括什么。

举个例子:

【小松教你手游开发】【unity实用技能】u3d 层次问题总结_第1张图片
像这个界面可以分成几块:
【小松教你手游开发】【unity实用技能】u3d 层次问题总结_第2张图片
每一块都可以分成一个UIPanel,每个UIPanel控制自己的Depth和透明度。可以处理好之间的遮挡问题。

以上是NGUI的基本渲染逻辑, 但是NGUI会自动把同一界面的同一张图集的东西一起渲染,也就是不管你这里几个UIPanel,UIPanel的Depth是3,4,5,还是30,40,50,只要是同一张图集的就会一起渲染。再通过加成计算算出前后关系。但是这里会有一个问题,就是假如你有两张图集,两张图集的图片的Depth相互交叉,这样会导致NGUI无法识别同一图集,导致渲染出错,导致更多的Drawcall。

例:如果在同一个atlas的两个sprite的depth不同比如1,3.在同一panel中有另一个atlas(比如字体)的depth在他们中间,比如2.就是
atlas1_sprite:depth 1
font_label:depth 2
atlas1_sprite:depth 3
这样不是两个drawcalls是三个

这个就是导致为什么在在不同情况下Depth会控制不了渲染顺序的原因。
所以这里一般项目就会有一个比较取巧的方法避免。
1.UI只用一张图集,2.字体的Depth放到300以上。

然后在完成一个UIPanel后需要检查一下,Drawcall是否正常。这个可以在NGUI的工具里打开Drawcall Tool来查看。(目标是把相同图集的Drawcall合并成一个)

之后的UIPanel的问题都会通过UIPanel和UIWidget的Depth来解决