一:前言

RectMask2D是矩形遮罩组件,继承自UIBehaviour、IClipper(裁剪者)、ICanvasRaycastFilter
它只能裁剪一个矩形区域,不依赖于Graphic


二:实现原理

OnEnable时将当前RectMask2D对象添加到裁剪者序列中(ClipperRegistry.Register),接着计算当前RectMask2D下所有可被裁剪的子对象并添加到相对应的RectMask2D待裁剪序列中(m_ClipTargets或m_MaskableTargets),画布更新时会依次调用裁剪者序列中的每个元素的PerformClipping方法实现具体裁剪操作,最终是由Shader实现的裁剪,当Shader接收到矩形区域后,片元着色器中判断像素是否在矩形区域内,不在则透明度设置为0,Shader会丢弃掉alpha小于0.001的元素

UGUI源码解析——RectMask2D_unity


三:​​源码​​解析

——AddClippable

UGUI源码解析——RectMask2D_2d_02


添加裁剪对象

设置m_ShouldRecalculateClipRects为true,接着判断裁剪对象是否为MaskableGraphic,并添加到IClippable序列或MaskableGraphic序列中,最后将m_ForceClip设置为true

此方法在MaskableGraphic类的UpdateClipParent方法中被调用,将所有待裁剪对象添加到当前RectMask2D的待裁剪序列中中 ——RemoveClippable

UGUI源码解析——RectMask2D_unity_03


移除裁剪对象

设置m_ShouldRecalculateClipRects为true,接着调用裁剪对象的SetClipRect方法关闭矩形裁剪,接着判断裁剪对象是否为MaskableGraphic,并从IClippable序列或MaskableGraphic序列中移除,最后将m_ForceClip设置为true

此方法在MaskableGraphic类的UpdateClipParent方法中被调用 ——OnEnable

UGUI源码解析——RectMask2D_unity_04


首先将自身添加到裁剪序列中,然后调用Notify2DMaskStateChanged方法遍历子对象中挂载了实现IClippable接口的对象(待裁剪对象),调用每个待裁剪对象的RecalculateClipping方法,将待裁剪对象添加到相对应RectMask2D的待裁剪序列中 ——OnDisable

UGUI源码解析——RectMask2D_实现原理_05


清空IClippable序列、MaskableGraphic序列、RectMask2D序列,并将自身从裁剪者序列中移除,最后调用Notify2DMaskStateChanged方法遍历子对象中挂载了实现IClippable接口的对象(待裁剪对象),调用每个待裁剪对象的RecalculateClipping方法,将待裁剪对象添加到相对应RectMask2D的待裁剪序列中——PerformClipping

UGUI源码解析——RectMask2D_嵌套_06


实现裁剪操作

如果m_ShouldRecalculateClipRects为true,则调用GetRectMasksForClip方法找到父对象身上所有有效的RectMask2D组件(为了处理RectMask2D组件嵌套的情况,因为当有两个RectMask2D时,裁切范围是两个共同作用的区域),接着调用Clipping.FindCullAndClipWorldRect方法计算裁切区域,当确定了裁剪区域后,对m_ClipTargets和m_MaskableTargets序列中每一个待裁剪元素进行裁剪(SetClipRect)和设置渐变度(UpdateClipSoftness)

此方法在ClipperRegistry类中的Cull方法中被调用