yyl
2025-09-18 871594462e82d6bc1341918d39e11ab036d59563
Main/Component/UI/Effect/BattleEffectPlayer.cs
@@ -30,13 +30,10 @@
        }
    }
    public bool isRedCamp = true;
    public EffectConfig effectConfig;
    public float speedRate = 1f;
    public float speedRate = 1.5f;
    [Header("播放完毕立即回收")]
@@ -44,11 +41,9 @@
    public Action<BattleEffectPlayer> onDestroy;
    [HideInInspector] public Canvas canvas = null;
    [HideInInspector] public GameObject effectTarget = null;
    protected EffectPenetrationBlocker blocker = null;
    protected RendererAdjuster blocker = null;
    protected bool isInit = false;
@@ -60,12 +55,18 @@
    protected GameObject spineContainer;
    protected SkeletonGraphic spineComp;
    protected SkeletonAnimation spineComp;
    protected Spine.AnimationState spineAnimationState;
    protected int heroSetedSortingOrder;
    public GameObjectPoolManager.GameObjectPool pool;
    public Action onComplete;
    private bool isPlaying = false;
    private float timer = 0f;
    protected virtual void OnEnable()
    {
@@ -107,13 +108,24 @@
        }
        //  初始化spine组件
        if (effectConfig != null && effectConfig.isSpine != 1)
        if (effectConfig != null && effectConfig.isSpine != 0)
        {
            GameObject spineContainerPrefab = ResManager.Instance.LoadAsset<GameObject>("UIComp", "SpineContainer");
            spineContainer = GameObject.Instantiate(spineContainerPrefab, transform);
            GameObject spineContainerPrefab = ResManager.Instance.LoadAsset<GameObject>("UIComp", "SpineAnimContainer");
            spineContainer = GameObject.Instantiate(spineContainerPrefab, transform, true);
            spineContainer.transform.localPosition = Vector3.zero;
        }
        //  有特效可能带spine又带unity特效的情况
        spineComp = gameObject.GetComponentInChildren<SkeletonGraphic>(true);
        spineComp = gameObject.GetComponentInChildren<SkeletonAnimation>(true);
        if (effectConfig.effectPos != null && effectConfig.effectPos.Length >= 2)
        {
            rectTrans.anchoredPosition += new Vector2((isRedCamp ? 1f : -1f) * effectConfig.effectPos[0], effectConfig.effectPos[1]);
        }
        if (effectConfig.effectScale > 0f)
        {
            rectTrans.localScale *= effectConfig.effectScale;
        }
    }
    protected virtual void Clear()
@@ -145,6 +157,27 @@
        Clear();
        onComplete?.Invoke();
    }
    public void SetSortingOrder(int _heroSetedSortingOrder)
    {
        heroSetedSortingOrder = _heroSetedSortingOrder;
        int so = heroSetedSortingOrder;
        if (null != blocker && effectConfig != null)
        {
            if (BattleConst.UnactiveHeroSortingOrder == heroSetedSortingOrder)
            {
                so = effectConfig.frontBack == 1 ? BattleConst.UnactiveHeroFrontSortingOrder : BattleConst.UnactiveHeroBackSortingOrder;
            }
            else
            {
                so = effectConfig.frontBack == 1 ? BattleConst.ActiveHeroFrontSortingOrder : BattleConst.ActiveHeroBackSortingOrder;
            }
            blocker.SetSortingOrder(so);
        }
    }
    public virtual void Play(bool showLog = true)
@@ -181,9 +214,34 @@
            this.gameObject.SetActive(true);
        }
        PlayEffect();
        isPlaying = true;
        timer = 0f;
        PlayEffect();
    }
    public void Run()
    {
        if (null == effectConfig)
        {
            return;
        }
        if (!isPlaying)
        {
            return;
        }
        if (effectConfig.autoDestroy != 0)
        {
            timer += Time.deltaTime * speedRate;
            if (timer >= effectConfig.destroyDelay)
            {
                GameObject.DestroyImmediate(gameObject);
            }
        }
    }
    protected virtual void PlayEffect()
@@ -194,6 +252,15 @@
            return;
        }
        //  如果delay小于等于0 那会立刻执行
        this.DelayTime(effectConfig.delayPlay, () =>
        {
            PlayEffectInternal();
        });
    }
    protected void PlayEffectInternal()
    {
        if (effectConfig.isSpine != 0)
        {
            PlaySpineEffect();
@@ -202,7 +269,6 @@
        {
            PlayUnityEffect();
        }
    }
    protected void PlaySpineEffect()
@@ -215,18 +281,43 @@
            return;
        }
        SkeletonDataAsset skeletonDataAsset = ResManager.Instance.LoadAsset<SkeletonDataAsset>("UIEffect/BattleSpine/" + effectConfig.packageName, effectConfig.fxName);
        SkeletonDataAsset skeletonDataAsset = ResManager.Instance.LoadAsset<SkeletonDataAsset>("UIEffect/" + effectConfig.packageName, effectConfig.fxName);
        spineComp.skeletonDataAsset = skeletonDataAsset;
        spineComp.Initialize(true);
        spineComp.raycastTarget = false;
        spineComp.timeScale = speedRate;
        spineAnimationState = spineComp.AnimationState;
        spineAnimationState = spineComp.state;
        spineAnimationState.Complete -= OnSpineAnimationComplete;
        spineAnimationState.Complete += OnSpineAnimationComplete;
        // 添加特效穿透阻挡器
        blocker = spineComp.AddMissingComponent<RendererAdjuster>();
        blocker.onSortingChanged = OnSortingChanged;
        spineComp.enabled = true;
        spineComp.timeScale = speedRate;
        spineAnimationState.TimeScale = speedRate;
        Spine.Animation animation = spineAnimationState.Data.SkeletonData.Animations.First();
        spineAnimationState.SetAnimation(0, animation, false);
        spineAnimationState.SetAnimation(0, animation, effectConfig.isLoop != 0);
        SoundPlayer.Instance.PlayUIAudio(effectConfig.audio);
    }
    private bool CheckForAdditiveBlend(Spine.Skeleton skeleton)
    {
        // 遍历所有插槽,检查是否有相加模式
        foreach (var slot in skeleton.Slots)
        {
            if (slot.Data.BlendMode == Spine.BlendMode.Additive)
            {
                return true;
            }
        }
        return false;
    }
    protected void PlayUnityEffect()
@@ -262,20 +353,44 @@
        OnUnityAnimationComplete();
        if (null == canvas)
            canvas = GetComponentInParent<Canvas>();
        // 添加特效穿透阻挡器
        blocker = effectTarget.AddMissingComponent<EffectPenetrationBlocker>();
        blocker = effectTarget.AddMissingComponent<RendererAdjuster>();
        //  如果没有canvas的话 正常是因为不在BattleWin下面的节点 意思就是当前没有显示 等到切回战斗的时候再通过BattleField.UpdateCanvas来更新
        if (canvas != null)
        {
            blocker.SetParentCanvas(canvas);
        }
        blocker.onSortingChanged = OnSortingChanged;
        SoundPlayer.Instance.PlayUIAudio(effectConfig.audio);
    }
    void LateUpdate()
    {
        if (string.IsNullOrEmpty(sortingLayer))
        {
            return;
        }
        OnSortingChanged(sortingLayer, sortingOrder);
    }
    public string sortingLayer;
    public int sortingOrder;
    public RectTransform rectTrans;
    protected void OnSortingChanged(string _sortingLayer, int _sortingOrder)
    {
        if (null == spineComp)
            return;
        sortingLayer = _sortingLayer;
        sortingOrder = _sortingOrder;
        // 处理排序变化
        var renderers = spineComp.GetComponents<Renderer>();
        foreach (var renderer in renderers)
        {
            renderer.sortingLayerName = sortingLayer;
            renderer.sortingOrder = sortingOrder;
        }
    }
    protected void OnDestroy()
@@ -325,25 +440,23 @@
    //  创建后的特效会自动隐藏 需要手动调用Play才能播放
    public static BattleEffectPlayer Create(int effectId, Transform parent, bool createNewChild = false)
    public static BattleEffectPlayer Create(int effectId, Transform parent, bool isRedCamp)
    {
        // 直接创建特效播放器,不使用对象池
        BattleEffectPlayer BattleEffectPlayer = null;
        BattleEffectPlayer battleEffectPlayer = null;
        if (createNewChild)
        {
            GameObject newGo = new GameObject("BattleEffectPlayer_" + effectId);
            newGo.transform.SetParent(parent, false);
            BattleEffectPlayer = newGo.AddComponent<BattleEffectPlayer>();
        }
        else
        {
            BattleEffectPlayer = parent.AddMissingComponent<BattleEffectPlayer>();
        }
        GameObject newGo = new GameObject("BattleEffectPlayer_" + effectId);
        newGo.transform.SetParent(parent, false);
        battleEffectPlayer = newGo.AddComponent<BattleEffectPlayer>();
        battleEffectPlayer.rectTrans = newGo.AddMissingComponent<RectTransform>();
        battleEffectPlayer.effectId = effectId;
        BattleEffectPlayer.effectId = effectId;
        BattleEffectPlayer.SetActive(true);
        return BattleEffectPlayer;
        // 设置阵营
        battleEffectPlayer.isRedCamp = isRedCamp;
        battleEffectPlayer.SetActive(true);
        return battleEffectPlayer;
    }
    /// <summary>
@@ -359,7 +472,7 @@
    public void Pause()
    {
        if (effectTarget == null) return;
        // if (effectTarget == null) return;
        // Spine动画
        // var spineGraphics = effectTarget.GetComponentsInChildren<SkeletonGraphic>(true);
@@ -367,6 +480,11 @@
        if (spineComp != null)
        {
            spineComp.timeScale = 0f;
        }
        if (spineAnimationState != null)
        {
            spineAnimationState.TimeScale = 0f;
        }
        // Animator动画
@@ -384,11 +502,16 @@
    public void Resume()
    {
        if (effectTarget == null) return;
        // if (effectTarget == null) return;
        if (spineComp != null)
        {
            spineComp.timeScale = speedRate;
        }
        if (spineAnimationState != null)
        {
            spineAnimationState.TimeScale = speedRate;
        }
        // Animator动画
@@ -438,21 +561,18 @@
        return true;
    }
    /// <summary>
    /// 设置遮罩(支持RectMask2D、Mask、SmoothMask等)
    /// </summary>
    public void SetMask(RectTransform maskArea = null)
    public void SetSpeedRatio(float ratio)
    {
        if (effectTarget == null || blocker == null)
            return;
        // 优先使用传入的maskArea
        if (maskArea != null)
        speedRate = ratio;
        if (spineComp != null)
        {
            blocker.PerformMask(maskArea);
            return;
            spineComp.timeScale = speedRate;
        }
        // Animator动画
        foreach (var animator in animatorList)
        {
            animator.speed = speedRate;
        }
    }
}