From 3bd7f56906e31e8fe0072108c9d4652707b51de8 Mon Sep 17 00:00:00 2001
From: yyl <yyl>
Date: 星期二, 21 十月 2025 17:59:00 +0800
Subject: [PATCH] 125 战斗 战斗UI

---
 Main/Component/UI/Effect/EffectPlayer.cs |  518 +++++++++++++++++++++++++++++++++++++++++++++++----------
 1 files changed, 426 insertions(+), 92 deletions(-)

diff --git a/Main/Component/UI/Effect/EffectPlayer.cs b/Main/Component/UI/Effect/EffectPlayer.cs
index cc2211a..3fdbc6c 100644
--- a/Main/Component/UI/Effect/EffectPlayer.cs
+++ b/Main/Component/UI/Effect/EffectPlayer.cs
@@ -4,14 +4,53 @@
 using Spine.Unity;
 using UnityEngine;
 using Spine;
+using UnityEngine.UI;
+using Cysharp.Threading.Tasks;
 
+// 鐗规晥鎾斁鍣紝棰勫埗浣撳璞℃睜绠$悊锛寀nity鐨勯鍒朵綋姹犱娇鐢ㄦ湁闂锛�1涓壒鏁�1涓睜浣嗗鐢ㄥ張浣庯級鍚庣画淇敼
+// unity鐗规晥銆婇鍒朵綋銆嬫槸鐗规晥甯堝湪鍒朵綔鐨勬椂鍊欑敓鎴愮殑涓嶅悓棰勫埗浣擄紝unity鐗规晥蹇呴』鎸傝浇璁剧疆鎾斁鏃堕暱鑴氭湰 EffectTime
+// spine鐗规晥鏄壒鏁堝笀鍒朵綔鐨勫姩鐢绘枃浠讹紝鍙叡鍚屽鐢ㄤ竴涓�婇鍒朵綋銆�
 public class EffectPlayer : MonoBehaviour
 {
-    public int effectId;
+    [SerializeField]
+    private int m_EffectID;
+    public int effectId
+    {
+        get
+        {
+            return m_EffectID;
+        }
+        set
+        {
+            if (value != m_EffectID)
+            {
+                Stop();
+                isInit = false;
+                m_EffectID = value;
+            }
+        }
+    }
 
-    public bool autoDestroy = false;
 
-    public float destroyDelay = 0f;
+
+    public EffectConfig effectConfig;
+
+    public float speedRate = 1f;
+
+    [Header("鏄惁寰幆鎾斁spine鐗规晥")]
+    public bool isPlaySpineLoop = false;
+
+    [Header("鏄惁鍦ㄦ樉绀烘椂鎾斁")]
+    public bool isPlayOnEnable = false;
+
+    [Header("寤惰繜鎾斁(姣)")]
+    public int playDelayTime = 0;
+
+    public int playSpineAnimIndex = -1; //鎾斁spine鐗规晥鍔ㄧ敾绱㈠紩,浠g爜鎺у埗
+
+
+    [Header("鎾斁瀹屾瘯绔嬪嵆鍥炴敹")]
+    public bool isReleaseImmediately = false;  //鐣岄潰鐗规晥涓�鑸笉闇�瑕佽嚜鎴戦攢姣侊紝璺熼殢鐣岄潰鎴栬�呯埗瀵硅薄閿�姣佸氨琛�
 
     public Action<EffectPlayer> onDestroy;
 
@@ -21,102 +60,333 @@
 
     protected EffectPenetrationBlocker blocker = null;
 
-    protected void Start()
+    protected bool isInit = false;
+    public bool isPlaying
     {
-        ReStart();
+        get;
+        protected set;
     }
 
-    public void Stop()
+    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 Spine.AnimationState spineAnimationState;
+
+    public GameObjectPoolManager.GameObjectPool pool;
+
+    public Action onComplete;
+
+    protected virtual void OnEnable()
     {
-        if (null != effectTarget)
+        
+        if (isPlayOnEnable)
         {
-            DestroyImmediate(effectTarget);
-            effectTarget = null;
+            Play(false);
+        }
+        else if (spineComp != null)
+        {
+            if (!isPlaying)
+            {
+                //闅愯棌锛屼細鏈夐潤鎬佹樉绀洪棶棰�
+                spineComp.enabled = false;
+            }
         }
     }
 
-    public void Play()
+    protected void InitComponent(bool showLog = true)
     {
-        if (!isActiveAndEnabled)
+        if (effectId <= 0)
         {
-            gameObject.SetActive(true);
-        }
-        ReStart();
-    }
-
-
-    protected void ReStart()
-    {
-        if (EffectMgr.Instance.IsNotShowBySetting(effectId))
-        {
+            effectConfig = null;
+#if UNITY_EDITOR
+            if (showLog)
+            {
+                Debug.LogError("EffectPlayer effectId is not set");
+                UnityEditor.Selection.activeGameObject = gameObject;
+                UnityEditor.EditorGUIUtility.PingObject(gameObject);
+            }
+#endif
             return;
         }
 
-        if (null != effectTarget)
-        {
-            DestroyImmediate(effectTarget);
-            effectTarget = null;
-        }
+        effectConfig = EffectConfig.Get(effectId);
 
-        EffectConfig effectCfg = EffectConfig.Get(effectId);
-
-        if (null == effectCfg)
+        if (null == effectConfig)
         {
+#if UNITY_EDITOR
+            Debug.LogError("could not find effect config, effect id is " + effectId);
+            UnityEditor.Selection.activeGameObject = gameObject;
+            UnityEditor.EditorGUIUtility.PingObject(gameObject);
+#endif
             return;
         }
 
-        //	YYL TODO
-        //	鍦ㄨ繖閲岃�冭檻鐢ㄦ睜鐨勮瘽鍙兘璧伴厤缃ソ涓�鐐� 鍘熸湰鐨勬槸鏃犺濡備綍閮借蛋姹� 浣嗘槸瀹為檯涓婃湁浜涚壒鏁堝苟涓嶉渶瑕�
+        Clear();
+        return;
+    }
 
-        // 鍔犺浇鐗规晥璧勬簮
-        var effectPrefab = ResManager.Instance.LoadAsset<GameObject>("UIEffect/" + effectCfg.packageName, effectCfg.fxName);
+    protected virtual void Clear()
+    {
+        isInit = false;
+        particleList.Clear();
+        animatorList.Clear();
+        rendererList.Clear();
+
+        if (spineComp != null)
+        {
+            spineComp.skeletonDataAsset = null;
+            // spineComp.Initialize(false);    
+            spineComp.Clear();
+        }
+
+        spineComp = null;
+    }
+
+    public virtual void Stop()
+    {
+        if (null != effectTarget)
+        {
+            // 濡傛灉浣跨敤浜嗙壒鏁堥鍒朵綋姹狅紝鍒欏綊杩樺埌姹犱腑
+            if (pool != null)
+            {
+                pool.Release(effectTarget);
+            }
+            effectTarget = null;
+        }
+        if (spineComp != null)
+        {
+            spineComp.enabled = false;
+        }
+        isPlaying = false;
+        playSpineAnimIndex = -1;
+    }
+
+    protected void Release()
+    {
+        Stop();
+
+        Clear();
+    }
+
+    public virtual void Play(bool showLog = true, bool closePMA = false)
+    {
+        isPlaying = true;
+        if (!isInit)
+        {
+            InitComponent(showLog);
+            //effeid 涓�0涔熷垵濮嬪寲鎴愬姛锛岄伩鍏嶉噸澶嶅鐞嗭紝鍦ㄥ彉鏇磂ffectid鏃朵細閲嶆柊鍒濆鍖�
+            isInit = true;
+        }
+        else
+        {
+            //閬垮厤閲嶅鍒涘缓
+            if (!this.gameObject.activeSelf)
+            {
+                this.gameObject.SetActive(true);
+            }
+            //闃茶寖effeid 涓�0
+            if (effectConfig != null && effectConfig.isSpine != 0)
+            {
+                PlaySpineEffect(closePMA);
+            }
+            return;
+        }
+        if (effectConfig == null)
+            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(closePMA);
+        }
+        else
+        {
+            PlayerEffect();
+        }
+    
+        SoundPlayer.Instance.PlayUIAudio(effectConfig.audio);
+
+    }
+
+
+    // protected virtual void PlaySpineEffect()
+    // {
+    //     spineComp = gameObject.GetComponentInChildren<SkeletonGraphic>(true);
+    //     spineComp.raycastTarget = false;
+    //     spineComp.Initialize(true);
+    //     spineAnimationState = spineComp.AnimationState;
+    //     spineAnimationState.Complete -= OnSpineAnimationComplete;
+    //     spineAnimationState.Complete += OnSpineAnimationComplete;
+
+    //     // 澶栧眰鎺у埗鍏蜂綋鎾斁鍝釜鍔ㄧ敾
+    //     spineComp.enabled = true;
+
+    //     return;
+    // }
+
+
+
+    protected void PlaySpineEffect(bool closePMA = false)
+    {
+
+        // 浠庣壒鏁堥鍒朵綋姹犺幏鍙栫壒鏁�
+        if (spineComp == null)
+        { 
+            spineComp = gameObject.AddMissingComponent<SkeletonGraphic>();
+        }
+
+        if (spineComp.skeletonDataAsset == null || spineAnimationState == null)
+        {
+            //LoadAsset 宸茬粡鏈夌紦瀛楽keletonDataAsset
+            spineComp.skeletonDataAsset = ResManager.Instance.LoadAsset<SkeletonDataAsset>("UIEffect/" + effectConfig.packageName, effectConfig.fxName);
+            //涓簍rue鏃朵細鏈夐儴鍒嗙壒鏁堜笉鏄剧ず 濡備富鐣岄潰瑁呭鐗规晥锛涙敼鎴愪冀椹悗涓嶄細鍑虹幇BUG鏁呮敞閲婁唬鐮�
+            // spineComp.MeshGenerator.settings.pmaVertexColors = !closePMA;   
+            spineComp.raycastTarget = false;
+            spineComp.Initialize(true);
+            spineComp.timeScale = speedRate;
+            // 妫�鏌ュ姩鐢绘槸鍚︽湁鐩稿姞妯″紡
+            // 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;
+            // }
+            spineComp.material = ResManager.Instance.LoadAsset<Material>("Materials", "SkeletonGraphicDefault-Straight");
+
+            spineAnimationState = spineComp.AnimationState;
+            spineAnimationState.Data.DefaultMix = 0f;
+            spineAnimationState.Complete -= OnSpineAnimationComplete;
+            spineAnimationState.Complete += OnSpineAnimationComplete;
+        }
+
+        spineComp.enabled = true;
+        PlayerTheSpineAnim();
+    }
+
+        // 鎾斁鎸囧畾鍔ㄧ敾
+    void PlayerTheSpineAnim()
+    {
+        spineComp.enabled = true;
+        var skeletonData = spineComp.Skeleton.Data;
+        if (skeletonData.Animations.Count > 0)
+        {
+            //鎸夐厤缃垨鑰呴粯璁ょ涓�涓�
+            int defaultAnimIndex = Math.Max(0, effectConfig.animIndex.Length == 0 ? 0 : effectConfig.animIndex[0]);
+            if (playSpineAnimIndex >= skeletonData.Animations.Count)
+            {
+                playSpineAnimIndex = -1;
+                Debug.LogError("鐗规晥锛�" + effectConfig.id + " 绱㈠紩瓒呭嚭鎾斁榛樿鍔ㄧ敾銆� error锛�" + playSpineAnimIndex);
+            }
+            string defaultAnimationName = skeletonData.Animations.Items[playSpineAnimIndex == -1 ? defaultAnimIndex : playSpineAnimIndex].Name;
+            spineAnimationState.SetAnimation(0, defaultAnimationName, isPlaySpineLoop);
+        }
+        else
+        {
+            Debug.LogError("Spine 鏁版嵁涓病鏈夋壘鍒颁换浣曞姩鐢伙紒" + effectConfig.id);
+        }
+    }
+
+
+    private bool CheckForAdditiveBlend(Spine.Skeleton skeleton)
+    {
+        // 閬嶅巻鎵�鏈夋彃妲斤紝妫�鏌ユ槸鍚︽湁鐩稿姞妯″紡
+        foreach (var slot in skeleton.Slots)
+        {
+            if (slot.Data.BlendMode == Spine.BlendMode.Additive)
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+
+
+    //unity鐗规晥
+    protected virtual void PlayerEffect()
+    {
+        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}";
+        if (effectConfig.isSpine == 0)
+        {
+            //unity鐗规晥 鍒ゆ柇棰勫埗浣撴槸鍚︽寕杞紼ffectTime
+            var timeObj = effectPrefab.GetComponent<EffectTime>();
+            if (null == timeObj)
+            {
+                Debug.LogError($"{effectPrefab.name}棰勫埗浣撴病鏈夋寕杞紼ffectTime");
+                return;
+            }
+        }
+
+        // 浠庣壒鏁堥鍒朵綋姹犺幏鍙栫壒鏁�
+        pool = GameObjectPoolManager.Instance.RequestPool(effectPrefab);
+        effectTarget = pool.Request();
+        // 璁剧疆鐖惰妭鐐瑰拰浣嶇疆
+        effectTarget.transform.SetParent(transform);
+        effectTarget.transform.localPosition = Vector3.zero;
+        effectTarget.transform.localScale = Vector3.one;
+        effectTarget.transform.localRotation = Quaternion.identity;
+        effectTarget.name = $"Effect_{effectConfig.fxName}";
+
+
+        //鎸傝浇缁勪欢鍚� 寮�濮嬫敹闆�
+        particleList.AddRange(gameObject.GetComponentsInChildren<ParticleSystem>(true));
+        animatorList.AddRange(gameObject.GetComponentsInChildren<Animator>(true));
+        rendererList.AddRange(gameObject.GetComponentsInChildren<Renderer>(true));
+        OnUnityAnimationComplete();
+    
 
         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();
-
-        // 鑷姩閿�姣�
-        if (autoDestroy)
+        //  濡傛灉娌℃湁canvas鐨勮瘽 姝e父鏄洜涓轰笉鍦˙attleWin涓嬮潰鐨勮妭鐐� 鎰忔�濆氨鏄綋鍓嶆病鏈夋樉绀� 绛夊埌鍒囧洖鎴樻枟鐨勬椂鍊欏啀閫氳繃BattleField.UpdateCanvas鏉ユ洿鏂�
+        if (canvas != null)
         {
-            Destroy(effectTarget, destroyDelay);
+            blocker.SetParentCanvas(canvas);
         }
     }
 
-    public void SetSortingOrderOffset(int offset)
+    public async UniTask PlayAsync(bool showLog = true, bool closePMA = false)
     {
-        // 琚獶estroy涔嬪悗effectTarget == null 涓� true 浣嗘槸璁块棶鍐呭浼氭姤閿�
-        if (blocker != null && effectTarget != null)
+        await UniTask.Delay(playDelayTime);
+        try
         {
-            blocker.sortingOrderOffset = offset;
-            blocker.UpdateSortingOrder();
+            Play(showLog, closePMA);
         }
-        else
+        catch (Exception e)
         {
-            blocker = null;
-            effectTarget = null;
+            Debug.LogError(e);
         }
     }
 
@@ -127,11 +397,58 @@
             onDestroy.Invoke(this);
             onDestroy = null;
         }
+        // 鍋滄鐗规晥骞跺綊杩樺埌姹犱腑
+        Release();
+
+        if (spineAnimationState != null)
+        {
+            spineAnimationState.Complete -= OnSpineAnimationComplete;
+        }
+
+
     }
 
-    //  鍒涘缓鍚庣殑鐗规晥浼氳嚜鍔ㄩ殣钘� 闇�瑕佹墜鍔ㄨ皟鐢≒lay鎵嶈兘鎾斁
-    public static EffectPlayer Create(int effectId, Transform parent, bool createNewChild = false, bool _autoDestroy = true, float _destroyDelay = 5f)
+    //鍗曟鎾斁瀹屾瘯灏变細瑙﹀彂锛屽嵆浣挎槸寰幆
+    protected virtual void OnSpineAnimationComplete(Spine.TrackEntry trackEntry)
     {
+        if (!isPlaySpineLoop)
+        {
+            spineComp.enabled = false;
+            isPlaying = false;
+            onComplete?.Invoke();
+            // TODO 浼氭姤閿欐殏鏃舵敞閲�
+            // if (isReleaseImmediately)
+            // {
+            //     Release();
+            // }
+
+        }
+    }
+
+
+    private void OnUnityAnimationComplete()
+    {
+        var timeObj = effectTarget.GetComponent<EffectTime>();
+        if (!timeObj.isLoop)
+        {
+            this.SetWait(timeObj.playTime);
+            this.DoWaitRestart();
+            this.OnWaitCompelete(OnEffectComplete);
+        }
+    }
+
+    private void OnEffectComplete(Component comp)
+    {
+        this.DoWaitStop();
+        if (isReleaseImmediately)
+            Release();
+    }
+
+
+    //  鍒涘缓鍚庣殑鐗规晥浼氳嚜鍔ㄩ殣钘� 闇�瑕佹墜鍔ㄨ皟鐢≒lay鎵嶈兘鎾斁
+    public static EffectPlayer Create(int effectId, Transform parent, bool createNewChild = false)
+    {
+        // 鐩存帴鍒涘缓鐗规晥鎾斁鍣紝涓嶄娇鐢ㄥ璞℃睜
         EffectPlayer effectPlayer = null;
 
         if (createNewChild)
@@ -143,35 +460,44 @@
         else
         {
             effectPlayer = parent.AddMissingComponent<EffectPlayer>();
-            effectPlayer.effectId = effectId;
-            effectPlayer.autoDestroy = _autoDestroy;
-            effectPlayer.destroyDelay = _destroyDelay;
         }
-        effectPlayer.SetActive(false);
+
+        effectPlayer.effectId = effectId;
+        effectPlayer.SetActive(true);
         return effectPlayer;
     }
+
+    /// <summary>
+    /// 璁剧疆娓告垙瀵硅薄婵�娲荤姸鎬�
+    // /// </summary>
+    // public void SetActive(bool active)
+    // {
+    //     if (gameObject != null)
+    //     {
+    //         gameObject.SetActive(active);
+    //     }
+    // }
 
     public void Pause()
     {
         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 +507,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 +530,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 +548,7 @@
         }
 
         // 绮掑瓙鐗规晥
-        var particles = effectTarget.GetComponentsInChildren<ParticleSystem>(true);
-        foreach (var ps in particles)
+        foreach (var ps in particleList)
         {
             if (ps.IsAlive())
             {
@@ -242,4 +558,22 @@
 
         return true;
     }
+
+    /// <summary>
+    /// 璁剧疆閬僵锛堟敮鎸丷ectMask2D銆丮ask銆丼moothMask绛夛級
+    /// </summary>
+    public void SetMask(RectTransform maskArea = null)
+    {
+        if (effectTarget == null || blocker == null)
+            return;
+
+        // 浼樺厛浣跨敤浼犲叆鐨刴askArea
+        if (maskArea != null)
+        {
+            blocker.PerformMask(maskArea);
+            return;
+        }
+    }
+
+
 }

--
Gitblit v1.8.0