lcy
2025-10-16 3b64befcd8b2ab5abef1a33c5c8f73a6b245aff0
Main/Component/UI/Effect/UIEffectPlayer.cs
@@ -11,184 +11,22 @@
//UI特效大部分情况不会改变特效,无需销毁
public class UIEffectPlayer : EffectPlayer
{
    [Header("是否循环播放spine特效")]
    public bool isPlaySpineLoop = false;
    [Header("是否在显示时播放")]
    public bool isPlayOnEnable = false;
    [Header("延迟播放(毫秒)")]
    public int playDelayTime = 0;
    int playSpineAnimIndex = -1; //播放spine特效动画索引,
    protected override void OnEnable()
    {
        playSpineAnimIndex = -1;
        if (isPlayOnEnable)
        {
            PlayAsync(false).Forget();
        }
        else if (spineComp != null)
        {
            if (!isPlaying)
            {
                //隐藏,会有静态显示问题
                spineComp.enabled = false;
            }
        }
    }
    public override void Play(bool showLog = true)
    {
        isPlaying = true;
        if (!isInit)
        {
            InitComponent(showLog);
            isInit = true;
        }
        else
        {
            //避免重复创建
            if (!this.gameObject.activeSelf)
            {
                this.gameObject.SetActive(true);
            }
            if (effectConfig.isSpine != 0)
            {
                PlayerTheSpineAnim();
            }
            return;
        }
        if (EffectMgr.IsNotShowBySetting(effectId))
        {
            return;
        }
        if (null != effectTarget)
        {
            if (pool != null)
                pool.Release(effectTarget);
            effectTarget = null;
        }
        if (!this.gameObject.activeSelf)
        {
            this.gameObject.SetActive(true);
        }
        // 加载spine特效资源
        if (effectConfig.isSpine != 0)
        {
            PlaySpineEffect();
        }
        else
        {
            PlayerEffect(false);
        }
        SoundPlayer.Instance.PlayUIAudio(effectConfig.audio);
    }
    protected override void PlaySpineEffect()
    {
        if (spineComp == null)
        {
            spineComp = gameObject.AddMissingComponent<SkeletonGraphic>();
        }
        if (spineComp.skeletonDataAsset == null)
        {
            //LoadAsset 已经有缓存SkeletonDataAsset
            spineComp.skeletonDataAsset = ResManager.Instance.LoadAsset<SkeletonDataAsset>("UIEffect/" + effectConfig.packageName, effectConfig.fxName);
            spineComp.raycastTarget = false;
            spineComp.Initialize(true);
            // 检查动画是否有相加模式
            bool hasAdditiveBlend = CheckForAdditiveBlend(spineComp.Skeleton);
            if (hasAdditiveBlend)
            {
                spineComp.material = ResManager.Instance.LoadAsset<Material>("UIEffect/" + effectConfig.packageName, effectConfig.fxName.Split('_')[0] + "_Material-Additive");
            }
            else
            {
                spineComp.material = null;
            }
            spineAnimationState = spineComp.AnimationState;
            spineAnimationState.Data.DefaultMix = 0f;
            spineAnimationState.Complete -= OnSpineAnimationComplete;
            spineAnimationState.Complete += OnSpineAnimationComplete;
        }
        spineComp.enabled = true;
        PlayerTheSpineAnim();
    }
    private bool CheckForAdditiveBlend(Spine.Skeleton skeleton)
    {
        // 遍历所有插槽,检查是否有相加模式
        foreach (var slot in skeleton.Slots)
        {
            if (slot.Data.BlendMode == Spine.BlendMode.Additive)
            {
                return true;
            }
        }
        return false;
    }
    public void Play(int index, bool showLog = true)
    //spine里的第几个动画,!!closePMA参数无效暂时留着
    public void Play(int index, bool showLog = true, bool closePMA = false)
    {
        playSpineAnimIndex = index;
        PlayAsync(showLog).Forget();
        PlayAsync(showLog, closePMA).Forget();
    }
    async UniTask PlayAsync(bool showLog = true)
    //配置动画组数组索引
    public void PlayByArrIndex(int index, bool showLog = true, bool closePMA = false)
    {
        await UniTask.Delay(playDelayTime);
        Play(showLog);
        var config = EffectConfig.Get(effectId);
        playSpineAnimIndex = index < config.animIndex.Length ? config.animIndex[index] : 0;
        PlayAsync(showLog, closePMA).Forget();
    }
    // 播放指定动画
    void PlayerTheSpineAnim()
    {
        spineComp.enabled = true;
        var skeletonData = spineComp.Skeleton.Data;
        if (skeletonData.Animations.Count > 0)
        {
            string defaultAnimationName = skeletonData.Animations.Items[playSpineAnimIndex == -1 ? effectConfig.animIndex : playSpineAnimIndex].Name;
            spineAnimationState.SetAnimation(0, defaultAnimationName, isPlaySpineLoop);
        }
        else
        {
            Debug.LogError("Spine 数据中没有找到任何动画!" + effectConfig.id);
        }
    }
    //单次播放完毕就会触发,即使是循环
    protected override void OnSpineAnimationComplete(Spine.TrackEntry trackEntry)
    {
        if (!isPlaySpineLoop)
        {
            spineComp.enabled = false;
            isPlaying = false;
            if (isReleaseImmediately)
            {
                Stop();
            }
            else
            {
                onComplete?.Invoke();
            }
        }
    }
    //  创建后的特效会自动隐藏 需要手动调用Play才能播放
@@ -212,4 +50,12 @@
    }
   public void SetEnabled(bool isEnable)
   {
      if (spineComp == null)
      {
         return;
      }
      spineComp.enabled = isEnable;
   }
}