#unity/日常积累 ## Unity 3D - [Mask](https://so.csdn.net/so/search?q=Mask&spm=1001.2101.3001.7020)和RectMask2D区别 : ### 主要区别: - **区别1: Mask主要处理不规则图形遮罩效果 RectMask2D只能做矩形遮罩.** ![[Pasted image 20240104144906.png]] ![[Pasted image 20240104144916.png]] 区别2: Mask需要一个Image来当作遮罩区域,子节点在Image[渲染区域]才会显示 RectMask2D以自身RectTransform为裁剪区域,子节点在[RectTransform区域]内显示 从效果上看 Mask+无图Image是可以替代RectMask2D , 但是为什么还存在RectMask2D呢? 先看下官方文档给出的说明 ![[Pasted image 20240104144930.png]] **最重要的是最后一条[性能优势]** **新建一个场景,默认drawcall(batches)数是2(天空盒1个drawcall, Camera1个drawcall).** ![[Pasted image 20240104144955.png]] **现在添加一个Mask(Mask对象上有一个Image组件,子节点也是一个Image)** ![[Pasted image 20240104145005.png]] ![[Pasted image 20240104145008.png]] **drawcall从2上升到5, 一个Mask导致增加了3个drawcall.** ![[Pasted image 20240104145015.png]] **通过Frame Debug工具查到drawcall来源 Mask导致2个drawcall(第1个和第3个,一头一尾),Mask下的子节点Image导致1个drawcall(中间的)** ![[Pasted image 20240104145021.png]] **再看下RectMask2D的情况(隐藏Mask, 显示RectMask2D)** ![[Pasted image 20240104145028.png]] **drawcall为3, 只有新增1个drawcall.** ![[Pasted image 20240104145036.png]] **从Frame Debug可以看出就是子节点Image导致的1个drawcall, 而RectMask2D不会导致drawcall.** **从Frame Debug可以看出就是子节点Image导致的1个drawcall, 而RectMask2D不会导致drawcall.** 结论 : 到这里可以暂时得出结论,如果只用固定矩形遮罩,不需要特殊形状遮罩的情况下,可以优先使用RectMask2D. (例如常见于scrollview的情况下,创建scrollview默认是Mask,可以选择手动替换成RectMask2D,大多数情况都适用,会有些许性能提升) 进阶内容 : 把Mask复制一个出来Mask(1), 然后把位置摆开, 让2个Mask别重叠(后面会解释为什么不重叠). ![[Pasted image 20240104145057.png]] **摆成这个样子(不重叠就行)** ![[Pasted image 20240104145103.png]] 然后再看一下drawcall情况, 还是5个drawcall, 没有变化. Unity把2个Mask进行了网格合并, 3个drawcall, 分别为[2个Mask头]、[2个Image]、[2个Mask尾]. 这里可以看出, Mask之间是可以进行合并的, 从而不额外增加drawcall ![[Pasted image 20240104145113.png]] **刚才强调不要重叠,现在看下如果重叠的话会出现什么情况** **现在把2个Mask摆成下图这样.** **刚才强调不要重叠,现在看下如果重叠的话会出现什么情况** **现在把2个Mask摆成下图这样.** ![[Pasted image 20240104145126.png]] **然后会发现drawcall飙升至8.** ![[Pasted image 20240104145146.png]] 这是因为Unity的合批需要同渲染层级(depth), 同材质, 同图集, 如果重叠了, depth就不同了, 6个drawcall分别为Mask头、Mask的Image、Mask尾、Mask(1)头、Mask(1)的Image、Mask(1)尾. 把2个Mask位置还原, 然后在Mask外创建一个Image, 看看Mask和外部的合并情况. ![[Pasted image 20240104145203.png]] **drawcall为6, 增加了1个drawcall, 说明Mask内外无法合批** ![[Pasted image 20240104145210.png]] **然后把外部Image的Hierarchy的层级降低(2个Mask下面)** ![[Pasted image 20240104145219.png]] **然后把Image放到Mask下** ![[Pasted image 20240104145226.png]] **然后drawcall变成了9, 因为破坏了一个Mask的depth, 导致2个Mask无法合批, 这也再次验证了, Unity的合批需要depth相同.** ![[Pasted image 20240104145234.png]] **最后看一下这种情况下的drawcall顺序** **7个drawcall从上到下分别为Mask(1)的头、蓝色Image、Mask的头、Mask(1)的Image、Mask(1)尾、Mask的Image、Mask的尾.** ![[Pasted image 20240104145241.png]] Mask还有其他情况这里就不多做测试了 Mask小结: 1.多个Mask之间可以进行合批(头和头合批, 子对象和子对象合批, 尾和尾合批),需要同渲染层级(depth), 同材质, 同图集. 2.Mask内外不能进行合批. 再试试RectMask2D 把RectMask2D复制一个出来RectMask2D(1), 然后把位置摆开. ![[Pasted image 20240104145253.png]] **然后看drawcall为4, 因为RectMask2D本身不会导致drawcall, 所以RectMask2D之间不能进行合批.** ![[Pasted image 20240104145300.png]] RectMask2D小结: 1.RectMask2D本身不产生drawcall. 2.不同RectMask2D的子对象不能合批. 总结 : 如果界面只需要一个遮罩, 推荐使用RectMask2D, 如果界面需要多个遮罩, 根据情况分析, 看多个遮罩之间能否合批, 如果可以则可以考虑使用Mask. 小提示 : 根据UGUI源码, 嵌套Mask不能超过9层, 超过部分会使用默认材质, 超出部分遮罩失效. ![[Pasted image 20240104145310.png]] ![[Pasted image 20240104145316.png]]