Unity3D :关于UGUI的网格重建、动静分离[通俗易懂]

Unity3D :关于UGUI的网格重建、动静分离[通俗易懂]前言:无论是网上的攻略还是以前的经验来说,都说UGUI需要进行动静分离。也就是说同一个界面下的UI,可活动的元素放在一个Canvas下,不可活动的元素放在另一个Canvas下。虽然两个Canvas打断了合批,但是却减少了网格的重建时间,总体上是有优化的。究其原因,是因为在同一个Canvas下的某个元素发生变化时,同一Canvas下的所有元素都会进行网格重建(ReBatch)。而静态的元素在…

大家好,又见面了,我是你们的朋友全栈君。

1、 前言:

        无论是网上的攻略还是以前的经验来说,都说UGUI需要进行动静分离。也就是说同一个界面下的UI,可活动的元素放在一个Canvas下,不可活动的元素放在另一个Canvas下。虽然两个Canvas打断了合批,但是却减少了网格的重建时间,总体上是有优化的。

        究其原因,是因为在同一个Canvas下的某个元素发生变化时,同一Canvas下的所有元素都会进行网格重建(ReBatch)。而静态的元素在逻辑上是不需要重建的,因为他们都没变过,所以需要分开。

        但是我在实际进行测试的时候(5.6.6)却发现在Profile中没有体现:

        创建了200个图片,其中100个在活动,另外100个静止。无论是怎么划分Canvas,其Rebuild次数始终为200(每一个Image的重建需要调用2次Rebuild)。简单地说,你动静分离也好,不分离也好,都是变化几个元素重建几次,而且从CPU时间来看也没有任何区别。那是不是说动静分离没什么用了?反正分不分都一样。

2、 正文:

        后来在网上咨询了各路大佬,最终了解到了其中的原因。下面谈谈我自己的理解(可能有误,知道大概意思就好)。

        参考:

        《Fill-rate, Canvases and input》:https://unity3d.com/cn/learn/tutorials/topics/best-practices/fill-rate-canvases-and-input?playlist=30089&tdsourcetag=s_pcqq_aiomsg

         Making the UI Backend Faster》:Making the UI Backend Faster | Unity Blog

        《关于Unity中的UGUI优化,你可能遇到这些问题》:关于Unity中的UGUI优化,你可能遇到这些问题 – UWA Blog

2.1、网格重建的过程:

        UGUI的网格重建分为两部分:一部分是是重新计算画布内的各个元素的顶点,并进行合并。第二部分是将整理好后的网格、贴图等数据拿去渲染。

        显然,无论是否进行动静分离,第二部分的消耗都是不变的,无非是占用几个DrawCall而已。所以动静分离的优化在于第一部分。

        UGUI在显示UI元素的时候,其实是为每一个UI元素(例如图片)建立一个网格,并且设置UV和颜色值等。对于使用同一个图集的元素,还会对其网格进行合并,从而使得这一批元素只占用1个DrawCall就可以渲染出来。从原理上讲,这部分的消耗也是必不可少的。在Unity中,这部分的工作在 Canvas.BuildBatch 中体现。

        但是在之前的Unity(5.2 以前)都还能在Profile里面看到 Canvas.BuildBatch这个方法的性能消耗。然而这之后的Unity便不能看到他的消耗,只能看到他的一个几乎不耗时的工作分配(JobAlloc.Grow),至少在5.6.6是这样的。

        那么,Unity对这个操作是做了怎样的优化呢?

2.2、5.2以后对Canvas.BuildBatch做的优化

        在5.2之后对 Canvas.BuildBatch 流程做了优化,一部分是算法的优化,另一部分是流程的优化。

        算法不讨论。流程方面,在CPU超过一个核心的情况下,Unity将Canvas.BuildBatch流程放在在主线程之外,使用多线程进行计算。由于不再占用主线程的时间,因此BuildBatch的消耗就可以忽略不计了。由于在另外的线程里面,所以只要那个线程没有超负荷,我们在主线程看到的Profile怎么看都不会有差。

        根据文章 《Fill-rate, Canvases and input》的介绍来看,反正是没有必要建立那么多的Canvas,几个画布就OK了:

        In Unity 5.2, the batching code was substantially rewritten, and is considerably more performant compared to Unity 4.6, 5.0 and 5.1. Further, on devices with more than 1 core, the Unity UI system will move most of the processing to worker threads. In general, Unity 5.2 reduces the need for aggressively splitting a UI into dozens of Sub-canvases. Many UIs on mobile devices can now be made performant with as few as two or three Canvases.

        综上可知:Unity将 Canvas.BuildBatch 的过程,也就是网格重建的过程放在了子线程中,从而减少了主线程的压力。但是这部分的工作量却是依旧存在的,只是官方建议我们没必要使用多个Canvas。我猜测是因为优化后的网格重建的消耗 小于 DrawCall 的消耗,所以以优化DrawCall为主。

2.3、Canvas仍可用于Text和Image的分离

        虽然动静分离的意义不大了,但是Text和Image的分离的意义还是很大的。经测试,多个Text和多个Image分处于两个独立的节点,在绘制是并不一定是先绘制完Image,再绘制Text。具体情况比较复杂,可能是先绘制一两个Image,然后一两个Text,然后继续绘制。他的合批计算比较复杂,从经验来看大概是类似“一层一层堆积”的感觉。先是最底一层的控件在窗口内进行平铺,铺满后算一层,有多少批次算多少。然后再往上铺一层,再算一次合批。

        所以Text和Image穿插,会导致可以在同一层合批的图片/文本被分隔在了不同的“层”,导致合批中断。

        最为方便的操作方式是将Image和Text各自的父节点各挂载一个Canvas,这样就能实现强制分组。至少在Canvas下的同一字体的Text就一定是在一批中了。

3、 总结:

        新版的Unity(5.2+)将 Canvas.BuildBatch 放在了其他线程进行操作,而现在的手机一般都是多核(骁龙650就是6核了),电脑也是,所以动静分离的优化不会对帧率造成影响。过多的Canvas反而会打断合批,增加DrawCall,其实也是需要取舍的。不过即便在别的线程里面操作,也是要进行运算的,运算多一些CPU发热手机就会降频,这也是很麻烦的事情。

        只能说动静分离之类的操作在新的版本下没有那么有必要,但是也不是没有没有用,有点鸡肋。

        不过在测试的时候,如果使用了上千个变化的UI元素和上千个不变的元素进行测试,还是能发现动静分离的差别的。其实这个原因猜测是用于计算Canvas.BuildBatch的线程耗时已经超过了主线程,造成掉帧。不过在一般的游戏中,是不存在这么多UI元素的,所以也不用担心。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/142901.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • mac如何查看已连接wifi的密码「建议收藏」

    mac如何查看已连接wifi的密码「建议收藏」可以通道mac自带的“钥匙串访问”功能查看。选择需要查询的wifi名称,右击选择“将密码拷贝到剪贴板”,输入管理员密码后,密码就拷贝好了。找个地方粘贴即可看到密码

    2022年8月4日
    9
  • idea集成svn使用教程_idea导入svn项目

    idea集成svn使用教程_idea导入svn项目1.查看svn仓库调出svn视图:连接svn服务器:连接后效果如下:补充:如果输入正确的连接地址后出现错误—系统找不到指定的文件请到设置中检查(File|Settings|VersionControl|Subversion)SVC客户端路径配置的对不对(选中bin目录下的svn.exe)?如果找不到svn.exe,看下图解释2.Idea集成svn如果不小心选错了其他选项,比如cvs,可以在settings中重新选择;…

    2022年10月18日
    0
  • 圆柱体体积的计算公式圆柱体积的计算公式_圆的面积计算公式

    圆柱体体积的计算公式圆柱体积的计算公式_圆的面积计算公式圆柱体体积计算公式?长方形的周长=(长+宽)×2正方形的周长=边长×4长方形的面积=长×宽正方形的面积=边长×边长三角形的面积=底×高÷2平行四边形的面积=底×高梯形的面积=(上底+下底)×高÷2直径=半径×2半径=直径÷2圆的周长=圆周率×直径=圆周率×半径×2圆的面积=圆周率×半径×半径长方体的表面积=(长×宽+长×高+宽×高)×2长方体的体积=长×宽×高正方体的表面积=棱长×棱长×6正…

    2022年9月20日
    0
  • 2021前端面试经常被问到的题(附答案)

    2021前端面试经常被问到的题(附答案)一、html二、css1.50道CSS基础面试题(附答案)50道CSS基础面试题(附答案)2.如何居中div?CSS水平居中+垂直居中+水平/垂直居中的方法总结3.CSS3新特性深入了解CSS3新特性4.清除浮动清除浮动的四种方式及其原理理解5.media媒体查询深入浅出篇—media媒体查询-响应式开发必备6.讲一讲Flex布局,以及常用的属性?一…

    2022年8月29日
    1
  • java c++ 学哪个_c++和java区别 学哪个比较好

    java c++ 学哪个_c++和java区别 学哪个比较好尽管Java是基于C++的,但是相比之下,Java是一种更纯粹的面向对象程序设计语言。Java的运用方面比c++要广一些。Java主要包括Web开发、移动互联开发等,应用场景较多,市场的需求量上来看Java程序员的市场需求量更大一些。Java和C++有什么不同1、Java源码会先经过一次编译,成为中间码,中间码再被解释器解释成机器码。对于Java而言,中间码就是字节码(、class),而解释器在…

    2022年7月9日
    19
  • HikariPool 连接池问题

    HikariPool 连接池问题前言:今天在一个项目运行的时候发现一个很奇怪的问题,当我有一段时间无操作之后再进行操作的话,就会出现HikariPool相关的报错,在此记录一下问题2022-02-2013:14:04.178WARN4012—[nio-8888-exec-6]com.zaxxer.hikari.pool.PoolBase:HikariPool-1-Failedtovalidateconnectioncom.mysql.cj.jdbc.ConnectionImpl@.

    2022年6月23日
    27

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号