一.前言
在Unity UGUI的性能优化中经常能看见,使用RectMask2D替换Mask,因为Mask会产生额外的Drwcall,而RectMask2D不会产生额外的Drwcall。但是RectMask2D的性能一定比Mask好吗?
二.Mask源码分析
public class Mask : UIBehaviour, ICanvasRaycastFilter, IMaterialModifier
Mask代码在190行左右。
Mask本身不具有绘制属性不继承Graphic,必须依赖带有Graphic的组件,节点如果没有如Image Text等组件Mask无法添加。
ICanvasRaycastFilter是表明Mask是射线可以投射的目标,ScreenPointToWorldPointInRectangle就是根据摄像机的位置和屏幕位置创建射线,根据RectTransform创建Plane,调用Plane.Raycast检测PM2.5与射线是否相交。
public static bool ScreenPointToWorldPointInRectangle(
RectTransform rect,
Vector2 screenPoint,
Camera cam,
out Vector3 worldPoint)
{
worldPoint = (Vector3) Vector2.zero;
Ray ray = RectTransformUtility.ScreenPointToRay(cam, screenPoint);
Plane plane = new Plane(rect.rotation * Vector3.back, rect.position);
float enter = 0.0f;
if ((double) Vector3.Dot(Vector3.Normalize(rect.position - ray.origin), plane.normal) != 0.0 && !plane.Raycast(ray, out enter))
return false;
worldPoint = ray.GetPoint(enter);
return true;
}
IMaterialModifier,得到修改的材质,在Canvas重绘时,如果Material是dirty会调用此方法更新材质,Mask实现的重点在GetModifiedMaterial上
Material GetModifiedMaterial(Material baseMaterial)
MaskEnabled()在获取材质之前确保物体active,有graphic渲染组件
FindRootSortOverrideCanvas找到节点上面最近是overrideSorting覆盖排序的的Canvas
public virtual Material GetModifiedMaterial(Material baseMaterial)
{
if (!MaskEnabled())//MaskEnabled() { return IsActive() && graphic != null; }
return baseMaterial;
var rootSortCanvas = MaskUtilities.FindRootSortOverrideCanvas(transform);
var stencilDepth = MaskUtilities.GetStencilDepth(transform, rootSortCanvas);
if (stencilDepth >= 8)
{
Debug.LogWarning("Attempting to use a stencil mask with depth > 8", gameObje