hch
2025-07-23 2336d5e71a6ed9c00f9a86c29d7aa33b9a1e38d5
Main/Component/UI/Effect/EffectPlayer.cs
@@ -4,16 +4,17 @@
using Spine.Unity;
using UnityEngine;
using Spine;
using UnityEngine.UI;
public class EffectPlayer : MonoBehaviour
{
    public int effectId;
    public bool autoDestroy = false;
    public float destroyDelay = 0f;
    public EffectConfig effectConfig;
    public Action<EffectPlayer> onDestroy;
    public float speedRate = 1f;
    [HideInInspector] public Canvas canvas = null;
@@ -21,9 +22,63 @@
    protected EffectPenetrationBlocker blocker = null;
    protected bool isInit = false;
    protected List<ParticleSystem> particleList = new List<ParticleSystem>();
    protected List<Animator> animatorList = new List<Animator>();
    protected List<Renderer> rendererList = new List<Renderer>();
    protected SkeletonGraphic spineComp;
    protected void Start()
    {
        ReStart();
    }
    protected void InitCompnent()
    {
        if (effectId <= 0)
        {
            effectConfig = null;
            Debug.LogError("EffectPlayer effectId is not set");
#if UNITY_EDITOR
            UnityEditor.Selection.activeGameObject = gameObject;
            UnityEditor.EditorGUIUtility.PingObject(gameObject);
#endif
            return;
        }
        effectConfig = EffectConfig.Get(effectId);
        if (null == effectConfig)
        {
            Debug.LogError("could not find effect config, effect id is " + effectId);
#if UNITY_EDITOR
            UnityEditor.Selection.activeGameObject = gameObject;
            UnityEditor.EditorGUIUtility.PingObject(gameObject);
#endif
            return;
        }
        particleList.Clear();
        animatorList.Clear();
        rendererList.Clear();
        spineComp = null;
        if (effectConfig.isSpine != 0)
        {
            spineComp = gameObject.GetComponentInChildren<SkeletonGraphic>(true);
        }
        else
        {
            //  收集组件
            particleList.AddRange(gameObject.GetComponentsInChildren<ParticleSystem>(true));
            animatorList.AddRange(gameObject.GetComponentsInChildren<Animator>(true));
        }
        rendererList.AddRange(gameObject.GetComponentsInChildren<Renderer>(true));
    }
    public void Stop()
@@ -33,20 +88,29 @@
            DestroyImmediate(effectTarget);
            effectTarget = null;
        }
        isInit = false;
        particleList.Clear();
        animatorList.Clear();
        rendererList.Clear();
        spineComp = null;
    }
    public void Play()
    {
        if (!isActiveAndEnabled)
        {
            gameObject.SetActive(true);
        }
        ReStart();
    }
    protected void ReStart()
    {
        if (!isInit)
        {
            isInit = true;
            InitCompnent();
        }
        if (EffectMgr.Instance.IsNotShowBySetting(effectId))
        {
            return;
@@ -58,67 +122,42 @@
            effectTarget = null;
        }
        EffectConfig effectCfg = EffectConfig.Get(effectId);
        if (null == effectCfg)
        {
            return;
        }
        //   YYL TODO
        //   在这里考虑用池的话可能走配置好一点 原本的是无论如何都走池 但是实际上有些特效并不需要
        // 加载特效资源
        var effectPrefab = ResManager.Instance.LoadAsset<GameObject>("UIEffect/" + effectCfg.packageName, effectCfg.fxName);
        var effectPrefab = ResManager.Instance.LoadAsset<GameObject>("UIEffect/" + effectConfig.packageName, effectConfig.fxName);
        if (effectPrefab == null)
        {
            Debug.LogError($"加载UI特效失败: {effectCfg.packageName}");
            Debug.LogError($"加载UI特效失败: {effectConfig.packageName}");
            return;
        }
        // 实例化特效
        effectTarget = Instantiate(effectPrefab, transform);
        effectTarget.name = $"Effect_{effectCfg.fxName}";
        effectTarget.name = $"Effect_{effectConfig.fxName}";
        //  思考一下在没有挂在节点的时候
        if (null == canvas)
            canvas = GetComponentInParent<Canvas>();
        if (null == canvas)
        {
            Debug.LogError("can not find canvas for UIEffect " + effectId);
            return;
        }
        // 添加特效穿透阻挡器
        blocker = effectTarget.AddMissingComponent<EffectPenetrationBlocker>();
        blocker.parentCanvas = canvas;
        //  延迟一帧才生效
        this.DelayFrame(blocker.UpdateSortingOrder);
        // blocker.UpdateSortingOrder();
        //  如果没有canvas的话 正常是因为不在BattleWin下面的节点 意思就是当前没有显示 等到切回战斗的时候再通过BattleField.UpdateCanvas来更新
        if (canvas != null)
        {
            blocker.SetParentCanvas(canvas);
        }
        // 自动销毁
        if (autoDestroy)
        if (effectConfig.autoDestroy != 0)
        {
            Destroy(effectTarget, destroyDelay);
            Destroy(effectTarget, effectConfig.destroyDelay);
        }
    }
    public void SetSortingOrderOffset(int offset)
    {
        // 被Destroy之后effectTarget == null 为 true 但是访问内容会报错
        if (blocker != null && effectTarget != null)
        {
            blocker.sortingOrderOffset = offset;
            blocker.UpdateSortingOrder();
        }
        else
        {
            blocker = null;
            effectTarget = null;
        }
    }
    protected void OnDestroy()
    {
@@ -130,7 +169,7 @@
    }
    //  创建后的特效会自动隐藏 需要手动调用Play才能播放
    public static EffectPlayer Create(int effectId, Transform parent, bool createNewChild = false, bool _autoDestroy = true, float _destroyDelay = 5f)
    public static EffectPlayer Create(int effectId, Transform parent, bool createNewChild = false)
    {
        EffectPlayer effectPlayer = null;
@@ -144,10 +183,8 @@
        {
            effectPlayer = parent.AddMissingComponent<EffectPlayer>();
            effectPlayer.effectId = effectId;
            effectPlayer.autoDestroy = _autoDestroy;
            effectPlayer.destroyDelay = _destroyDelay;
        }
        effectPlayer.SetActive(false);
        effectPlayer.SetActive(true);
        return effectPlayer;
    }
@@ -156,22 +193,21 @@
        if (effectTarget == null) return;
        // Spine动画
        var spineGraphics = effectTarget.GetComponentsInChildren<SkeletonGraphic>(true);
        foreach (var sg in spineGraphics)
        // var spineGraphics = effectTarget.GetComponentsInChildren<SkeletonGraphic>(true);
        // foreach (var sg in spineGraphics)
        if (spineComp != null)
        {
            sg.timeScale = 0f;
            spineComp.timeScale = 0f;
        }
        // Animator动画
        var animators = effectTarget.GetComponentsInChildren<Animator>(true);
        foreach (var animator in animators)
        foreach (var animator in animatorList)
        {
            animator.speed = 0f;
        }
        // 粒子特效
        var particles = effectTarget.GetComponentsInChildren<ParticleSystem>(true);
        foreach (var ps in particles)
        foreach (var ps in particleList)
        {
            ps.Pause();
        }
@@ -181,23 +217,19 @@
    {
        if (effectTarget == null) return;
        // Spine动画
        var spineGraphics = effectTarget.GetComponentsInChildren<SkeletonGraphic>(true);
        foreach (var sg in spineGraphics)
        if (spineComp != null)
        {
            sg.timeScale = 1f;
            spineComp.timeScale = speedRate;
        }
        // Animator动画
        var animators = effectTarget.GetComponentsInChildren<Animator>(true);
        foreach (var animator in animators)
        foreach (var animator in animatorList)
        {
            animator.speed = 1f;
            animator.speed = speedRate;
        }
        // 粒子特效
        var particles = effectTarget.GetComponentsInChildren<ParticleSystem>(true);
        foreach (var ps in particles)
        foreach (var ps in particleList)
        {
            ps.Play();
        }
@@ -208,18 +240,13 @@
        if (effectTarget == null) return true;
        // Spine动画
        var spineGraphics = effectTarget.GetComponentsInChildren<SkeletonGraphic>(true);
        foreach (var sg in spineGraphics)
        if (!spineComp.AnimationState.GetCurrent(0).IsComplete)
        {
            if (!sg.AnimationState.GetCurrent(0).IsComplete)
            {
                return false;
            }
            return false;
        }
        // Animator动画
        var animators = effectTarget.GetComponentsInChildren<Animator>(true);
        foreach (var animator in animators)
        foreach (var animator in animatorList)
        {
            AnimatorStateInfo stateInfo = animator.GetCurrentAnimatorStateInfo(0);
@@ -231,8 +258,7 @@
        }
        // 粒子特效
        var particles = effectTarget.GetComponentsInChildren<ParticleSystem>(true);
        foreach (var ps in particles)
        foreach (var ps in particleList)
        {
            if (ps.IsAlive())
            {
@@ -242,4 +268,20 @@
        return true;
    }
    /// <summary>
    /// 设置遮罩(支持RectMask2D、Mask、SmoothMask等)
    /// </summary>
    public void SetMask(RectTransform maskArea = null)
    {
        if (effectTarget == null || blocker == null)
            return;
        // 优先使用传入的maskArea
        if (maskArea != null)
        {
            blocker.PerformMask(maskArea);
            return;
        }
    }
}