using System; 
 | 
using System.Collections.Generic; 
 | 
using Spine.Unity; 
 | 
using UnityEngine; 
 | 
using UnityEngine.UI; 
 | 
  
 | 
  
 | 
  
 | 
/// <summary> 
 | 
/// 特效穿透阻挡器 
 | 
/// 将此脚本挂在特效游戏对象上,可以防止特效穿透UI界面 
 | 
/// </summary> 
 | 
public class EffectPenetrationBlocker : MonoBehaviour 
 | 
{ 
 | 
    [Tooltip("是否在UI层级下自动调整排序顺序")] 
 | 
    public bool autoAdjustSorting = true; 
 | 
  
 | 
    [Tooltip("特效渲染器,如果为空则自动获取")] 
 | 
    public List<Renderer> effectRenderers = new List<Renderer>(); 
 | 
  
 | 
    [Tooltip("自定义排序顺序,仅在不自动调整时有效")] 
 | 
    public int customSortingOrder = 0; 
 | 
  
 | 
    [Tooltip("自定义排序层,为空则使用默认UI层")] 
 | 
    public string customSortingLayer = "UI"; 
 | 
  
 | 
    [Tooltip("特效所属的Canvas,如果为空则查找父级Canvas")] 
 | 
    public Canvas parentCanvas; 
 | 
  
 | 
    [Tooltip("特效在Canvas中的排序偏移量")] 
 | 
    public int sortingOrderOffset = 1; 
 | 
  
 | 
    public int canvasSortingOrder = 0; 
 | 
  
 | 
    public int renderQueue = 3000;//默认值 
 | 
  
 | 
    public Action<string, int> onSortingChanged; 
 | 
  
 | 
    private void Awake() 
 | 
    { 
 | 
        transform.GetComponentsInChildren(true, effectRenderers); 
 | 
  
 | 
        // 如果没有指定渲染器,则自动获取 
 | 
        if (effectRenderers == null || effectRenderers.Count == 0) 
 | 
        { 
 | 
            transform.GetComponentsInChildren<Renderer>(true, effectRenderers); 
 | 
        } 
 | 
  
 | 
        // 查找父级Canvas 
 | 
        if (parentCanvas == null) 
 | 
        { 
 | 
            parentCanvas = GetComponentInParent<Canvas>(); 
 | 
        } 
 | 
  
 | 
        if (autoAdjustSorting) 
 | 
        { 
 | 
            UpdateSortingOrder(); 
 | 
        } 
 | 
        else 
 | 
        { 
 | 
            // 使用自定义排序 
 | 
            ApplySortingSettings(customSortingOrder, customSortingLayer); 
 | 
        } 
 | 
    } 
 | 
  
 | 
    private void OnEnable() 
 | 
    { 
 | 
        if (autoAdjustSorting) 
 | 
        { 
 | 
            UpdateSortingOrder(); 
 | 
        } 
 | 
    } 
 | 
  
 | 
    /// <summary> 
 | 
    /// 更新排序顺序,确保特效显示在当前UI界面上方 
 | 
    /// </summary> 
 | 
    public void UpdateSortingOrder() 
 | 
    { 
 | 
        if (!autoAdjustSorting) return; 
 | 
  
 | 
        // 获取父级Canvas的排序顺序 
 | 
        if (parentCanvas != null) 
 | 
        { 
 | 
            canvasSortingOrder = parentCanvas.sortingOrder; 
 | 
        } 
 | 
        else 
 | 
        { 
 | 
            // 如果没有找到父级Canvas,则使用默认值 
 | 
            canvasSortingOrder = 0; 
 | 
        } 
 | 
  
 | 
        // 将特效的排序顺序设置为Canvas排序顺序加上偏移量 
 | 
        ApplySortingSettings(canvasSortingOrder + sortingOrderOffset, customSortingLayer); 
 | 
    } 
 | 
  
 | 
    /// <summary> 
 | 
    /// 应用排序设置到所有渲染器和粒子系统 
 | 
    /// </summary> 
 | 
    private void ApplySortingSettings(int sortingOrder, string sortingLayer) 
 | 
    { 
 | 
        // const int overlayRQ = 4000; 
 | 
  
 | 
        // 应用到渲染器 
 | 
        foreach (Renderer renderer in effectRenderers) 
 | 
        { 
 | 
            if (renderer != null) 
 | 
            { 
 | 
                renderer.sortingOrder = sortingOrder; 
 | 
                renderer.material.renderQueue = renderQueue; // 设置渲染队列 
 | 
                // renderer.material.renderQueue = overlayRQ; 
 | 
                if (!string.IsNullOrEmpty(sortingLayer)) 
 | 
                { 
 | 
                    renderer.sortingLayerName = sortingLayer; 
 | 
                } 
 | 
            } 
 | 
        } 
 | 
  
 | 
        onSortingChanged?.Invoke(sortingLayer, sortingOrder); 
 | 
    } 
 | 
  
 | 
    /// <summary> 
 | 
    /// 手动设置排序顺序 
 | 
    /// </summary> 
 | 
    public void SetSortingOrder(int sortingOrder, string sortingLayer = null) 
 | 
    { 
 | 
        customSortingOrder = sortingOrder; 
 | 
        if (!string.IsNullOrEmpty(sortingLayer)) 
 | 
        { 
 | 
            customSortingLayer = sortingLayer; 
 | 
        } 
 | 
  
 | 
        autoAdjustSorting = false; 
 | 
        ApplySortingSettings(customSortingOrder, customSortingLayer); 
 | 
    } 
 | 
  
 | 
    /// <summary> 
 | 
    /// 设置父级Canvas 
 | 
    /// </summary> 
 | 
    public void SetParentCanvas(Canvas canvas) 
 | 
    { 
 | 
        parentCanvas = canvas; 
 | 
        if (autoAdjustSorting) 
 | 
        { 
 | 
            this.DelayFrame(UpdateSortingOrder); 
 | 
        } 
 | 
    } 
 | 
  
 | 
    /// <summary> 
 | 
    /// 应用遮罩区域(RectTransform),可用于裁剪特效 
 | 
    /// </summary> 
 | 
    public void PerformMask(RectTransform maskRect) 
 | 
    { 
 | 
        // 这里只是示例,实际可根据你的Shader或特效材质做裁剪 
 | 
        foreach (Renderer renderer in effectRenderers) 
 | 
        { 
 | 
            if (renderer != null && renderer.material != null && maskRect != null) 
 | 
            { 
 | 
                Vector3[] corners = new Vector3[4]; 
 | 
                maskRect.GetWorldCorners(corners); 
 | 
                Vector4 clipRect = new Vector4(corners[0].x, corners[0].y, corners[2].x, corners[2].y); 
 | 
                renderer.material.SetVector("_ClipRect", clipRect); 
 | 
                renderer.material.SetFloat("_UseClipRect", 1); 
 | 
            } 
 | 
            else if (renderer != null && renderer.material != null) 
 | 
            { 
 | 
                renderer.material.SetFloat("_UseClipRect", 0); 
 | 
            } 
 | 
        } 
 | 
    } 
 | 
  
 | 
  
 | 
#if UNITY_EDITOR 
 | 
    [ContextMenu("Apply")] 
 | 
    public void Apply() 
 | 
    { 
 | 
        UpdateSortingOrder(); 
 | 
    } 
 | 
#endif 
 | 
} 
 |