obsidian/笔记文件/2.笔记/Unity 3D - Mask和RectMask2D区别.md
2025-03-26 00:02:56 +08:00

4.9 KiB

#unity/日常积累

Unity 3D - Mask和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