zoukankan      html  css  js  c++  java
  • (转)NGUI中深度depth和z轴关系

    先列出转载链接:

    http://game.ceeger.com/forum/read.php?tid=8917

     

    转载原文:

     

    问题源自一个帖子,因为上传的图比较多,就另开了这个贴写下自己的试验结果,原帖在下面链接中
    http://game.ceeger.com/forum/read.php?tid=8911#info
    NGUI中是用depth来控制sprite显示顺序的,本来这很好用,但碰到上面帖子中的问题时却不好解决了,于是我试验了下。以下是一些总结,不对的地方请指正。
    下面的内容可能看起来比较绕,这样的话只需实际试验下就能很容易的知道结果,呵呵
    如果还是看不明白,可以先看1楼,那里有个总结
     
    1,同一个panel下,同一个atlas的不同sprite的显示只受depth的控制,这是最经常用的方式。此时不论精灵的z轴如何变化,depth高的一定在前面。
    比如精灵A的z轴是-10,更靠近相机,但它的depth是0,而精灵B的z轴是0但depth是1,那么精灵B还是显示在前面
    如下图,0、1、2的前缀分别是三者的depth值,则三者的排列就是如图的由下到上,2_Label在最上面

     
    现在在depth不变的前提下修改z轴的值。将0_Dark的z轴调为-100,则它离相机更近了,看上去应该挡住后面的两个才对,但Game场景中三者的关系并没有改变,也就是说虽然看上去0_Dark应该挡住后面的东西,但并没有这样,还是depth起作用,也就是feiben同学所说的“相同atlas其实是共用同一个Z轴深度”。

    2,不同panel下,同一个atlas的不同sprite不受depth的控制,而受z轴控制。此时只需稍微调节下其中一个精灵的z轴就可以,比如0.1,就可以控制sprite的显示
    比如接着1中的图,新建一个panel_B,将1_NGUI拖到里面,会看到它盖住了0和2,现在调节depth不起作用,无论1_NGUI的depth调成多少,都不会改变它在最上面的状态

    现在调节下1_NGUI的z轴为0.1,则它到了最后面

    而比如现在想把在panel_B中的1_NGUI重新显示在0和2之间,能办到么?经过试验会发现无论怎么调三者的z轴,都不能将NGUI放到0和2之间,因为它们是一个图集中的精灵,共用一个z轴深度
    比如将0_Dark的z设为100,此时1_NGUI的z轴还是0.1,但1_NGUI重新跑到了最上面,而不是中间

    再把Label的z设为-100,NGUI是被覆盖了,但Dark也跟着跑到了上面,注意此时三者的空间位置,NGUI的确是在中间的,但还是被后面的Dark挡住了

    你也许会感觉这是自找麻烦,没事把同一个atlas的精灵放到两个panel中干什么呢?一般情况下是自找麻烦,但为了解决上面帖子中提到的问题,这是个解决的办法,如3

    备注:我也重新做了一遍试验,2这种情况跟原文描述的不一样,我的如果两个panel自身的depth值不一样,那么panel大的那个的所有物件会覆盖在另外一个panel,即panel的depth大的物体后画,此时调z轴没有用,如果两个panel值一样,绘制的情况目前我还没有找出规律,但是可以确定的是跟调z轴也没有关系,因为我同一个panel下的两个物体调z轴改变不了覆盖关系,大depth的panel下的物体调z轴后也不能移到小panel的物体后面去,虽然在scene场景中会移动到后面,但运行后没有移动到后面。而且此时depth对物体的显示是有用的,比如同depth的panelA和PanelB,A下面挂了两个Sprite,B下面挂了一个Sprite,三个Sprite来自同一个altas,那么就是谁的Depth大谁就最后绘制。
    可以这样总结,每个widget的depth是根据 它自身的depth和它所在的Panel的depth位参数算出来的值,并且Panel的depth占了非常大比重。最终它们的绘制顺序还是依据的depth。
    不知道这跟版本有没有关系,我测试的版本是ngui 3.0。

    3,不同panel下,不同atlas的精灵的穿插,受z轴的控制。
    现在回到帖子中提出的问题,怎么让多个atlas的sprite能进行穿插。办法是用多个panel。
    比如有两个atlas,分别为SiFi和Wooden,而SiFi中有两个要显示的精灵Dark和Label,Wooden中有一个要显示的精灵wooden,现在想把wooden放到Dark和Label之间。那么设置两个panel,一个放Dark和wooden,另一个放Label,或者一个放Label和wooden,另一个放Dark,只要SiFi图集中的两个精灵不在同一个panel中就可以,之后微调其中一个精灵的z轴就可以了,比如调节Label的z轴为-0.1,则如下图,wooden到了Dark和Label的中间

     
    不过如果认为为什么要这么麻烦呢,只需要在一个panel中调节就可以了,那就回到了2中的问题上,总是在上或在下,而不会在中间
     
    如下图,三者在一个panel下,现在空间位置是wooden在中间z为0,Dark为100,Lable为-100,且三者的depth也是相应的,但wooden还是在最上面
    现在修改下wooden的z轴,比如改为1,而Dark和Label的z不变,则wooden跑到了最后面,但就是不到中间去
    此外,即使用两个panel,但同是SiFi图集中的Dark和Label还是在同一个panel下,而把wooden放到另一个panel中,还是无法达到插入的目的,如下图,无论怎么调节wooden的z轴,它要么在最前面,要么在最后面

    此时只需把Dark或Label之一放到wooden的panel下就能实现wooden在中间的目的,比如把Dark和wooden放到一起

    而现在有个有趣的想法,就是既然这样可以达到wooden在中间的目的,那能不能把label放到两者中间呢?试一下就知道,是可以的。而既然这样,那Dark能放到两者中间么,试一下,还是可以的。这就让定位更加灵活
     
    当然这是最简单的穿插,如果有多个panel和多个atlas的话情况会比较复杂,此时要记着2中的情况,否则还是容易出现无法穿插的问题。而解决这个问题的方法最好还是atlas设计的时候更全面,让穿插的sprite在一个atlas中,这样只用depth深度就可以控制了
     
    备注:这里我测试的还是和原文不一样,得出的结论还是widget的depth会根据它自身的depth值和它所在Panel的depth值进行计算,并且Panel的值会占非常大的比重,可以理解位Panel值大的一定比Panel小的widget后绘制。这里调z轴仍然没起作用。
     
    4,同一个panel下,不同Atlas的sprite,受z轴控制,depth不起作用。而默认添加的时候覆盖关系似乎和atlas有关,比如从SiFi图集和Wooden图集中分别添加任意一个精灵到同一个panel下,总是SiFi的精灵在下面,此时depth不起作用,可以直接调节z轴比如-0.1就可以

    备注:这个还是有问题,同一个panel下,不同Atlas的sprite还是只跟它们的depth有关系,跟z轴没有关系,同depth的画绘制顺序目前我没有能够找出规律。 

    5,(修改)对于panel是否会产生drawcall,之前的试验存在误区,当时是直接复制带着sprite的Panel,这的确会产生新的drawcall,这是因为在复制时panel的scale被修改了,由1变成了0.9999304之类的,这会导致drawcall增加了1个,而之后再复制这个由复制产生的panel,scale还是0.9999304,所以drawcall不会再变。
    现在发现修改panel的缩放scale的确会增加drawcall。所以如果为了方便而复制一个panel的话,别忘了reset它的缩放
     

    而之所以对panel是否会产生drawcall,是因为官方例7中只用了2个Atlas,但drawcall却是5个,当时简单的认为是panel的问题。

     

     

    ngui官网对Panel的depth的说明,两个Panel最好不要用相同的depth,否则ngui内部会拆分Drawcall来处理这种情况,会比较费。

    其实主要的是不知道这种情况下Panel的depth最后是以什么形式加权到下面的widgets的,所以没办法掌控。

    All panels have a Depth value which affects all widgets underneath. If you're creating a complex UI with multiple windows, it's often best to have one UIPanel per window. The depth value of panels carries a lot more weight than the depth value on individual widgets, so it's a good idea to ensure that your panels don't share depth values. If values get shared, draw calls will start to get split up frequently in order to preserve the draw order, resulting in a lot more draw calls than usual.

     

    我自己的测试的结论如下:

    每个Widget会根据一个算法公式将自己的depth和它所在的panel的depth合起来计算一个depth,并且它所在的panel的depth会占有非常大的比重,可以认定位panel大的,最后算出来的depth一定大,然后渲染的顺序严格按照最后算出来的depth从小到大排,大的后渲染。depth值一样大的,包括同一个panel下的所有同depth的widget和不同Panel下(但这些panel的depth相同)的所有同depth的widget的渲染顺序目前还没有发现规律,但不管怎样都跟z轴貌似没啥关系,有高手可以补充哈

  • 相关阅读:
    二分法查找算法
    [Java]事件驱动程序设计
    spring 事件驱动模型简介
    事件驱动模型实例详解(Java篇)
    协程
    事件驱动模型的简单Java实现
    负载均衡技术(一)———负载均衡技术介绍
    知物由学 | 未来50年网络安全行业发展愿景
    知物由学 | 如何从勒索软件的攻击中全身而退
    “网易大数据讲堂第一期:数说”直播活动资料:课程回放收看及PPT下载
  • 原文地址:https://www.cnblogs.com/wonderKK/p/4070222.html
Copyright © 2011-2022 走看看