5022f4efe76121df33dc81249befa7556e535418..4fde46699701b1a8b74b4dab516624852b24a86d
8 天以前 yyl
Merge branch 'master' of http://192.168.1.20:10010/r/Project_SG_scripts
4fde46 对比 | 目录
8 天以前 yyl
特效问题
8df61a 对比 | 目录
1个文件已修改
2个文件已添加
224 ■■■■■ 已修改文件
Main/Component/UI/Effect/EffectPlayer.cs 77 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Component/UI/Effect/EffectPlayer.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/UIBase/UIBase.cs 136 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Component/UI/Effect/EffectPlayer.cs
New file
@@ -0,0 +1,77 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EffectPlayer : MonoBehaviour
{
    public int effectId;
    public bool autoDestroy = false;
    public float destroyDelay = 0f;
    public Canvas canvas = null;
    public GameObject effectTarget = null;
    protected void Start()
    {
        if (EffectMgr.Instance.IsNotShowBySetting(effectId))
        {
            return;
        }
        if (null != effectTarget)
        {
            DestroyImmediate(effectTarget);
            effectTarget = null;
        }
        EffectConfig effectCfg = EffectConfig.Get(effectId);
        if (null == effectCfg)
        {
            return;
        }
        //    YYL TODO
        //    在这里考虑用池的话可能走配置好一点 原本的是无论如何都走池 但是实际上有些特效并不需要
        // 加载特效资源
        var effectPrefab = ResManager.Instance.LoadAsset<GameObject>("UIEffect/" + effectCfg.packageName, effectCfg.fxName);
        if (effectPrefab == null)
        {
            Debug.LogError($"加载UI特效失败: {effectCfg.packageName}");
            return;
        }
        // 实例化特效
        effectTarget = Instantiate(effectPrefab, transform);
        effectTarget.name = $"Effect_{effectCfg.packageName}";
        if (null == canvas)
            canvas = GetComponentInParent<Canvas>();
        if (null == canvas)
        {
            Debug.LogError("can not find canvas for UIEffect " + effectId);
            return;
        }
        // 添加特效穿透阻挡器
        EffectPenetrationBlocker blocker = effectTarget.AddComponent<EffectPenetrationBlocker>();
        blocker.parentCanvas = canvas;
        //  延迟一帧才生效
        this.DelayFrame(blocker.UpdateSortingOrder);
        // blocker.UpdateSortingOrder();
        // 自动销毁
        if (autoDestroy)
        {
            Destroy(effectTarget, destroyDelay);
        }
    }
}
Main/Component/UI/Effect/EffectPlayer.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9fd18e7f2fdcf8a4ab668f35a4d6817d
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/UIBase/UIBase.cs
@@ -329,143 +329,21 @@
    /// <param name="autoDestroy">是否自动销毁,默认为true</param>
    /// <param name="destroyDelay">自动销毁延迟时间,默认为5秒</param>
    /// <returns>特效游戏对象</returns>
    public GameObject PlayUIEffect(int id, Transform parent = null, bool autoDestroy = true, float destroyDelay = 5f)
    public EffectPlayer PlayUIEffect(int id, Transform parent = null, bool autoDestroy = true, float destroyDelay = 5f)
    {
        // 使用默认值
        if (parent == null) parent = transform;
        
        EffectConfig effectCfg = EffectConfig.Get(id);
        EffectPlayer player = parent.gameObject.AddComponent<EffectPlayer>();
        if (null == effectCfg)
        {
            return null;
        }
        player.effectId = id;
        player.autoDestroy = autoDestroy;
        player.destroyDelay = destroyDelay;
        player.canvas = canvas;
        // 加载特效资源
        var effectPrefab = ResManager.Instance.LoadAsset<GameObject>("UIEffect/" + effectCfg.packageName, effectCfg.fxName);
        if (effectPrefab == null)
        {
            Debug.LogError($"加载UI特效失败: {effectCfg.packageName}");
            return null;
        }
        // 实例化特效
        GameObject effectObj = Instantiate(effectPrefab, parent);
        effectObj.name = $"Effect_{effectCfg.packageName}";
        // 添加特效穿透阻挡器
        EffectPenetrationBlocker blocker = effectObj.AddComponent<EffectPenetrationBlocker>();
        blocker.parentCanvas = canvas;
        //  延迟一帧才生效
        this.DelayFrame(blocker.UpdateSortingOrder);
        // blocker.UpdateSortingOrder();
        // 自动销毁
        if (autoDestroy)
        {
            Destroy(effectObj, destroyDelay);
        }
        return effectObj;
        return player;
    }
    
    /// <summary>
    /// 在两个UI元素之间播放特效(按照sortingOrder的中间值)
    /// </summary>
    /// <param name="effectName">特效资源名称</param>
    /// <param name="frontElement">前景UI元素(Image或RawImage)</param>
    /// <param name="backElement">背景UI元素(Image或RawImage)</param>
    /// <param name="autoDestroy">是否自动销毁,默认为true</param>
    /// <param name="destroyDelay">自动销毁延迟时间,默认为5秒</param>
    /// <returns>特效游戏对象</returns>
    public async UniTask<GameObject> PlayEffectBetweenUIElements(string effectName, Graphic frontElement, Graphic backElement, bool autoDestroy = true, float destroyDelay = 5f)
    {
        if (frontElement == null || backElement == null)
        {
            Debug.LogError("前景或背景UI元素为空");
            return null;
        }
        // 确保UI元素在当前UIBase的Canvas下
        if (frontElement.canvas != canvas || backElement.canvas != canvas)
        {
            Debug.LogError("UI元素不在当前UIBase的Canvas下");
            return null;
        }
        // 加载特效资源
        GameObject effectPrefab = ResManager.Instance.LoadAsset<GameObject>("UIEffect", effectName);
        if (effectPrefab == null)
        {
            Debug.LogError($"加载UI特效失败: {effectName}");
            return null;
        }
        // 创建一个新的GameObject作为特效容器
        GameObject container = new GameObject($"EffectContainer_{effectName}");
        container.transform.SetParent(transform, false);
        // 设置容器位置
        RectTransform containerRect = container.AddComponent<RectTransform>();
        containerRect.anchorMin = new Vector2(0.5f, 0.5f);
        containerRect.anchorMax = new Vector2(0.5f, 0.5f);
        containerRect.pivot = new Vector2(0.5f, 0.5f);
        containerRect.anchoredPosition = Vector2.zero;
        containerRect.sizeDelta = new Vector2(100, 100); // 默认大小,可以根据需要调整
        // 获取前景和背景元素的siblingIndex
        int frontIndex = frontElement.transform.GetSiblingIndex();
        int backIndex = backElement.transform.GetSiblingIndex();
        // 设置特效容器的siblingIndex在两者之间
        if (frontIndex > backIndex)
        {
            // 前景在背景之后,特效应该在中间
            container.transform.SetSiblingIndex((frontIndex + backIndex) / 2 + 1);
        }
        else
        {
            // 背景在前景之后,特效应该在中间
            container.transform.SetSiblingIndex((frontIndex + backIndex) / 2);
        }
        // 实例化特效
        GameObject effectObj = Instantiate(effectPrefab, container.transform);
        effectObj.name = $"Effect_{effectName}";
        // 添加特效穿透阻挡器
        EffectPenetrationBlocker blocker = effectObj.AddComponent<EffectPenetrationBlocker>();
        // 直接设置特效渲染器的排序顺序
        Renderer[] renderers = effectObj.GetComponentsInChildren<Renderer>(true);
        foreach (Renderer renderer in renderers)
        {
            renderer.sortingOrder = canvas.sortingOrder;
            renderer.sortingLayerName = canvas.sortingLayerName;
        }
        // 设置粒子系统渲染器的排序顺序
        ParticleSystem[] particleSystems = effectObj.GetComponentsInChildren<ParticleSystem>(true);
        foreach (ParticleSystem ps in particleSystems)
        {
            ParticleSystemRenderer psRenderer = ps.GetComponent<ParticleSystemRenderer>();
            if (psRenderer != null)
            {
                psRenderer.sortingOrder = canvas.sortingOrder;
                psRenderer.sortingLayerName = canvas.sortingLayerName;
            }
        }
        // 自动销毁
        if (autoDestroy)
        {
            Destroy(container, destroyDelay);
        }
        return effectObj;
    }
    #endregion
    public bool raycastTarget