当前位置: 首页 > article >正文

面试题分析: Unity UGUI动静分离

近期有同学面试,被问到这样一道面试题:

”说说UGUI的动静分离是怎么一回事?”

关于这个优化有一些误区,容易让开发者陷入一个极端。我们先分析关于UGUI 合批优化的问题,最后给这个面试题一个参考回答。

对惹,这里有一个游戏开发交流小组,希望大家可以点击进来一起交流一下开发经验呀!

Unity UGUI 到底采用的是哪种合批技术?

Drawcall合批技术,我们一般是有动态合批,静态合批,GPU Instancing合批。对于GUI部分,游戏引擎合批一般采用哪些技术呢?这个取决于游戏引擎的实现,比如Unity UGUI采用的是静态合批,预先把Mesh等合并好,而Cocos Creator 引擎采用的是通用的动态合批。为什么不使用GPU Instancing合批呢?主要可能考虑有几个原因:半透明,九宫格,tiledmap等相关的处理,这类GPU Instancing不适合处理。不是所有的设备与显卡支持GPU Instancing, 兼容性不如动态合批or静态合批。所以大部分游戏引擎的UI,要么采用静态合批,要么采用动态合批。”静态合批与动态合批”都会导致一个问题,就是要重新计算与合并Mesh。”静态合批”合批的一个好处就是合并完后如果内部的UI元素没有位置等信息没有修改,就不用重新计算,渲染的时候直接把合并好的数据提交渲染就可以了。”动态合批”是遍历每个可以合批的UI元素,将数据合并后一起提交给GPU渲染。动态合批更灵活,更通用。

Unity UGUI 合批的开销分析

UGUI 是基于Canvas来进行合并计算的。这样会导致以下几个问题:

1: 不同Cavans的UI元素,是无法合批渲染,无法使用同一个drawcall;

2: 每次合并的时候,会合并计算Canvas下所有的UI元素, 具体的算法流程为:

Step1: 一开始计算合并Cavans下所有的UI元素;

Step2: 每帧提交合并后的结果给GPU渲染;

Step3: 当某个UI元素改变以后,先计算某个UI元素改变后的数据,再结合其它UI元素,重新合并到一起。

3: 每次UI元素的位置等相关信息改变,都会引发合并计算;

4: “不动物体”的合并计算开销是最小的,如果Cavans下所有的UI元素一旦创建都不再改变,那么合并计算这块只要计算一次,性能最好。

5: 当Cavans下有不断变化的物体时,每次都会有合并计算,此时不动的物体少,那么最后合并的时候物体的数据就少。

由上面的分析,很多人就得到一个结论: 动静分离,将不变的物体放一个canvas,变化的物体放一个canvas下,优化合并时候的开销。进而有人推导出来: “每个界面一个Cavans。然后面试时,被奉为经典,导致大家回答每个界面我们都做一个Canvas。减少Mesh合并的开销。”

每个UI界面都做Canvas到底有没有必要?

假设有两个界面,界面A(50个UI元素),界面B(50个UI元素), 他们可以合批。假设界面A中的所有UI元素都不变化,界面B中的每个UI元素的位置在不断的改变,我们来分别讨论:"界面A,界面B共用一个Canvas与界面A,界面B分开两个Cavans在合并上的开销"。

情况1: 界面A,界面B共用一个Cavans;

Step1: 计算界面A中每个UI节点元素转换后的位置等信息, 计算A50个元素,计算一次;

Step2: 计算界面B中每个UI节点元素转换后的位置等信息,计算B50个元素,由于变化,每次都计算

Step3: 将A的50个元素信息(只计算一次) + B的50个元素信息,合并成100大的mesh,一起提交;

情况2;界面A,界面B共用2个Cavavns;

Step1: 计算界面A中单个UI节点元素转换后的位置等信息, 计算A50个,计算一次;

Step2: 合并界面A中的所有的UI节点元素数据,合并计算一次,将结果每次提交给GPU渲染;

Step3: 计算界面B中单个UI节点元素转后的位置等信息,计算B50个,每次改变都计算;

Step3: 将B50个信息合并到一起,提交给GPU进行渲染,每次都要合并,将结果提交给GPU渲染;

仔细比对,我们发现,情况1优于情况2的是,A,B可以一起提交,节约drawcall。情况2优于情况1的是最后合并时,不用copy A的50个元素信息的数据,其它合并计算并没有太大的差别。

情况1比情况2能节约一个drawcall, 情况2比情况1在合并的时候,少copy 合并50个数据。

经上面分析,基于多Canvas的”动静分离”会打乱合批,能节省的是”合并时不变的元素的数据copy”。

总结: 没有必要每个UI界面都做一个Cavans, 一般我们做开发的时候,常规的游戏UI界面做一个Cavans, 大规模的弹出式滚动列表可以考虑做一个Cavans。游戏元素,如2D游戏中角色,2D/3D游戏中的玩家昵称,角色血条等,可以做一个Cavans。一般项目中2~3个Cavans就可以了。还是要把重点放在UI的drawcall优化上。

参考回答: 说说UGUI的动静分离是怎么一回事?

最后给出这个面试题的参考回答:

Unity UGUI 会基于Canvas,将能合并的UI元素,计算合并到一起,然后再提交给GPU渲染来节约Drawcall,在这个过程中,如果某个UI元素改变了,就会引发一次合并计算。”动静分离”一般指的是把那些不经常动的UI与经常动的2D元素分成不同的Cavans,来减少合并时候的开销。这个通常叫做”动静分离”。我们在开发项目的时候,会把经常变化的游戏元素(2D游戏角色,玩家昵称,玩家血条等)做到一个Cavans下。把通常的游戏操作UI界面做一个Cavans下,对于那些UI内容非常多的如”任务滚动列表”等,我们也会考虑单独做一个Cavans,然后持续监测UI性能即可。有人说每个界面做一个Cavans,个人觉得没有必要。如果UI部分有性能问题,再具体问题具体分析即可。

更多教学视频

Unity3D​www.bycwedu.com/promotion_channels/2146264125


http://www.kler.cn/a/409751.html

相关文章:

  • STM32编程小工具FlyMcu和STLINK Utility 《通俗易懂》破解
  • 问:Spring Boot应用监控组件工具,梳理一下?
  • shell编程之awk
  • 大数取模 详解
  • C++ 中数组作为参数传递时,在函数中使用sizeof 为什么无法得到数组的长度
  • 图论最短路(floyed+ford)
  • Java中使用FFmpeg拉取RTSP流
  • 『 Linux 』网络层 - IP协议 (二)
  • Flink——进行数据转换时,报:Recovery is suppressed by NoRestartBackoffTimeStrategy
  • Flink Standalone集群模式安装部署
  • Spring学习笔记_49——@ResponseBody
  • Spring Boot 开发环境搭建详解
  • 【八股文】小米
  • 【漏洞复现】|百易云资产管理运营系统/mobilefront/c/2.php前台文件上传
  • 云计算虚拟化-kvm-无损扩容磁盘分区
  • java-分而治之算法
  • 极简开源Windows桌面定时提醒休息python程序
  • 常见排序算法总结 (一) - 三种基本排序
  • Java爬虫与淘宝API接口:高效数据采集的结合
  • 搜索二叉树(增删查)
  • Linux——Uboot命令使用
  • git提交到远程仓库如何撤回?
  • Stable Diffusion 3 部署笔记
  • 开源电话机器人产品的优点是什么?
  • Linux系统中查看当前使用的显示管理器
  • 【FAQ】HarmonyOS SDK 闭源开放能力 — 公共模块