Unity Canvas+Mask嵌套问题
2023/11
03
16:11
Canvas+Mask嵌套
如果子级Canvas上面使用了Override Sorting,会导致父级的Mask,无法影响子级
原因:
Mask在子级Canvas上,进行了模板重置,所以增加一个Mask子类MaskAAA:
using System;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Rendering;
using UnityEngine.Serialization;
namespace UnityEngine.UI
{
[AddComponentMenu("UI/MaskAAA", 13)]
[ExecuteAlways]
[RequireComponent(typeof(RectTransform))]
[DisallowMultipleComponent]
/// <summary>
/// A component for masking children elements.
/// </summary>
/// <remarks>
/// By using this element any children elements that have masking enabled will mask where a sibling Graphic would write 0 to the stencil buffer.
/// </remarks>
public class MaskAAA : UnityEngine.UI.Mask
{
public bool m_ShowMaskGraphic { get { return showMaskGraphic; } }
private Material m_MaskMaterial;
private Material m_UnmaskMaterial;
/// Stencil calculation time!
public override Material GetModifiedMaterial(Material baseMaterial)
{
if (!MaskEnabled())
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", gameObject);
return baseMaterial;
}
int desiredStencilBit = 1 << stencilDepth;
// if we are at the first level...
// we want to destroy what is there
if (desiredStencilBit == 1)
{
var maskMaterial = StencilMaterial.Add(baseMaterial, 1, StencilOp.Replace, CompareFunction.Always, m_ShowMaskGraphic ? ColorWriteMask.All : 0);
StencilMaterial.Remove(m_MaskMaterial);
m_MaskMaterial = maskMaterial;
// var unmaskMaterial = StencilMaterial.Add(baseMaterial, 1, StencilOp.Zero, CompareFunction.Always, 0);
// StencilMaterial.Remove(m_UnmaskMaterial);
// m_UnmaskMaterial = unmaskMaterial;
// graphic.canvasRenderer.popMaterialCount = 1;
// graphic.canvasRenderer.SetPopMaterial(m_UnmaskMaterial, 0);
return m_MaskMaterial;
}
//otherwise we need to be a bit smarter and set some read / write masks
var maskMaterial2 = StencilMaterial.Add(baseMaterial, desiredStencilBit | (desiredStencilBit - 1), StencilOp.Replace, CompareFunction.Equal, m_ShowMaskGraphic ? ColorWriteMask.All : 0, desiredStencilBit - 1, desiredStencilBit | (desiredStencilBit - 1));
StencilMaterial.Remove(m_MaskMaterial);
m_MaskMaterial = maskMaterial2;
graphic.canvasRenderer.hasPopInstruction = true;
var unmaskMaterial2 = StencilMaterial.Add(baseMaterial, desiredStencilBit - 1, StencilOp.Replace, CompareFunction.Equal, 0, desiredStencilBit - 1, desiredStencilBit | (desiredStencilBit - 1));
StencilMaterial.Remove(m_UnmaskMaterial);
m_UnmaskMaterial = unmaskMaterial2;
graphic.canvasRenderer.popMaterialCount = 1;
graphic.canvasRenderer.SetPopMaterial(m_UnmaskMaterial, 0);
return m_MaskMaterial;
}
}
}
然后增加一个新的UI材质
把Stencil Comparison设置为6,放到子Canvas的Image上,即可
CopyRights: The Post by BY-NC-SA For Authorization,Original If Not Noted,Reprint Please Indicate From 老刘@开发笔记
Post Link: Unity Canvas+Mask嵌套问题
Post Link: Unity Canvas+Mask嵌套问题