using System; using System.Collections.Generic; using Spine.Unity; using UnityEngine; using UnityEngine.UI; /// /// 特效穿透阻挡器 /// 将此脚本挂在特效游戏对象上,可以防止特效穿透UI界面 /// public class EffectPenetrationBlocker : MonoBehaviour { [Tooltip("是否在UI层级下自动调整排序顺序")] public bool autoAdjustSorting = true; [Tooltip("特效渲染器,如果为空则自动获取")] public List effectRenderers = new List(); [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 onSortingChanged; private void Awake() { transform.GetComponentsInChildren(true, effectRenderers); // 如果没有指定渲染器,则自动获取 if (effectRenderers == null || effectRenderers.Count == 0) { transform.GetComponentsInChildren(true, effectRenderers); } // 查找父级Canvas if (parentCanvas == null) { parentCanvas = GetComponentInParent(); } if (autoAdjustSorting) { UpdateSortingOrder(); } else { // 使用自定义排序 ApplySortingSettings(customSortingOrder, customSortingLayer); } } private void OnEnable() { if (autoAdjustSorting) { UpdateSortingOrder(); } } /// /// 更新排序顺序,确保特效显示在当前UI界面上方 /// public void UpdateSortingOrder() { if (!autoAdjustSorting) return; // 获取父级Canvas的排序顺序 if (parentCanvas != null) { canvasSortingOrder = parentCanvas.sortingOrder; } else { // 如果没有找到父级Canvas,则使用默认值 canvasSortingOrder = 0; } // 将特效的排序顺序设置为Canvas排序顺序加上偏移量 ApplySortingSettings(canvasSortingOrder + sortingOrderOffset, customSortingLayer); } /// /// 应用排序设置到所有渲染器和粒子系统 /// 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); } /// /// 手动设置排序顺序 /// public void SetSortingOrder(int sortingOrder, string sortingLayer = null) { customSortingOrder = sortingOrder; if (!string.IsNullOrEmpty(sortingLayer)) { customSortingLayer = sortingLayer; } autoAdjustSorting = false; ApplySortingSettings(customSortingOrder, customSortingLayer); } /// /// 设置父级Canvas /// public void SetParentCanvas(Canvas canvas) { parentCanvas = canvas; if (autoAdjustSorting) { this.DelayFrame(UpdateSortingOrder); } } /// /// 应用遮罩区域(RectTransform),可用于裁剪特效 /// 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 }