From 64d526e0f5b9f49fe5bd6dcf043f5071d996e7ad Mon Sep 17 00:00:00 2001
From: yyl <yyl>
Date: 星期五, 24 四月 2026 11:04:29 +0800
Subject: [PATCH] 125 战斗 修复步练师的被动bug

---
 Main/System/Battle/BattleObject/BattleObject.cs     |    4 ++
 Main/System/Battle/Motion/MotionBase.cs             |   29 ++++++++++++++
 Main/System/Battle/BattleObject/HeroBattleObject.cs |    9 ++++
 Main/System/Battle/Skill/SkillBase.Finish.cs        |   16 ++++++++
 Main/System/Battle/Skill/SkillBase.Cast.cs          |   61 ++++++++++++++++++++++++++++++
 5 files changed, 119 insertions(+), 0 deletions(-)

diff --git a/Main/System/Battle/BattleObject/BattleObject.cs b/Main/System/Battle/BattleObject/BattleObject.cs
index b30a55c..12f5dd3 100644
--- a/Main/System/Battle/BattleObject/BattleObject.cs
+++ b/Main/System/Battle/BattleObject/BattleObject.cs
@@ -41,6 +41,10 @@
         battleField = _battleField;
     }
 
+    //  SkillBase.MoveToTarget 鍙戣捣鐨勫墠鍐� / 鍥炰綅 tween 鍙ユ焺锛堢敱 SkillBase 缁存姢锛夈��
+    //  CanCastSkillAnimation 鍙垽鏂繖涓�涓彞鏌勶紝閬垮厤璇激 caster 韬笂鍏跺畠涓氬姟 tween銆�
+    public Tween activeMoveTween;
+
     // ============ 鎶借薄璁块棶鏂规硶锛堝瓙绫昏繑鍥炲悇鑷殑Team绫诲瀷淇℃伅锛� ============
     
     public abstract int GetPositionNum();
diff --git a/Main/System/Battle/BattleObject/HeroBattleObject.cs b/Main/System/Battle/BattleObject/HeroBattleObject.cs
index df429c0..feceba8 100644
--- a/Main/System/Battle/BattleObject/HeroBattleObject.cs
+++ b/Main/System/Battle/BattleObject/HeroBattleObject.cs
@@ -198,6 +198,15 @@
     
     public override bool CanCastSkillAnimation(SkillSkinConfig skillSkinConfig)
     {
+        //  闄や簡绛� Spine 鎶�鑳藉姩鐢婚攣锛坧layingSkillWithAnim锛夛紝杩樺繀椤荤瓑 caster 鑷韩鐢� SkillBase.MoveToTarget
+        //  鍙戣捣鐨勫墠鍐� / 鍥炰綅 tween 璺戝畬銆傚惁鍒欎笂涓�涓妧鑳界殑鍥炰綅 tween 杩樺湪鍗婅矾锛屼笅涓�涓妧鑳斤紙灏ゅ叾鏄鍔�
+        //  BattleType=5锛変細鍦ㄥ綋鍓嶄綅缃啀鍙戣捣鍓嶅啿锛屾棫鍥炰綅 tween 鍜屾柊鍓嶅啿 tween 鍚屾椂鍐� anchoredPosition锛�
+        //  瑙嗚琛ㄧ幇鏄�"娌″洖浣嶅張绐佺劧鍐插嚭鍘绘敾鍑�"銆傝繖閲屽彧鍒ゅ畾 SkillBase 鑷繁璁板綍鐨勭Щ鍔� tween 鍙ユ焺锛屼笉璇激
+        //  鎸傚湪 heroRectTrans 涓婄殑鍏跺畠涓氬姟 tween銆�
+        if (activeMoveTween != null && activeMoveTween.IsActive() && !activeMoveTween.IsComplete())
+        {
+            return false;
+        }
         return motionBase.CanCastSkill(skillSkinConfig);
     }
     
diff --git a/Main/System/Battle/Motion/MotionBase.cs b/Main/System/Battle/Motion/MotionBase.cs
index 56be39a..12d5ef5 100644
--- a/Main/System/Battle/Motion/MotionBase.cs
+++ b/Main/System/Battle/Motion/MotionBase.cs
@@ -45,6 +45,13 @@
     private bool playingSkill = false;
 
     private bool _playingSkillWithAnim = false;
+#if UNITY_EDITOR
+    //  [鍗℃璇婃柇] 璁板綍鏄皝鎶� playingSkillWithAnim 閿佷负 true銆佸湪鍝竴甯э紝渚� SkillBase.ReportStuckIfNeeded 浣跨敤銆�
+    //  涓嶅仛 Run() 鍐� watchdog锛堥伩鍏嶅埛灞忥級锛涘彧鍦� SkillBase 鑷韩鍙戠幇鍗℃鏃朵竴娆℃�ф妸杩欎簺淇℃伅鎵撳嚭鏉ャ��
+    private int _pswaSetTrueFrame = -1;
+    private int _pswaSetTrueSkillId = 0;
+    private string _pswaSetTrueStack = null;
+#endif
     private bool playingSkillWithAnim
     {
         get => _playingSkillWithAnim;
@@ -58,6 +65,19 @@
                 // 姣忔鍙樻洿鎵撳嵃鏍堬紝瀹氫綅鍒板簳鏄皝鎶� playingSkillWithAnim 璁� true 浜嗐�佽皝娓�/涓嶆竻
                 BattleDebug.LogError($"[MotionBase owner={owner} hash={GetHashCode()}] playingSkillWithAnim {_playingSkillWithAnim} -> {value}\n"
                     + UnityEngine.StackTraceUtility.ExtractStackTrace());
+            }
+            //  [鍗℃璇婃柇] 缁存姢閿佺殑鎸佹湁鑰呬俊鎭紙涓婁竴杞殑瀛楁琚洖婊氫簡锛岃繖閲屾槸鏈�灏忓繀瑕侀泦鍚堬級
+            if (value && !_playingSkillWithAnim)
+            {
+                _pswaSetTrueFrame = UnityEngine.Time.frameCount;
+                _pswaSetTrueStack = UnityEngine.StackTraceUtility.ExtractStackTrace();
+                // skillId 鐢� ExecuteSkillAnim 绱ф帴鐫�璧嬪�硷紙setter 杩欓噷鎷夸笉鍒帮級
+            }
+            else if (!value && _playingSkillWithAnim)
+            {
+                _pswaSetTrueFrame = -1;
+                _pswaSetTrueSkillId = 0;
+                _pswaSetTrueStack = null;
             }
 #endif
             _playingSkillWithAnim = value;
@@ -335,6 +355,10 @@
             activeSkillTracks[trackIndex] = skillTrack;
 
             playingSkillWithAnim = true;
+#if UNITY_EDITOR
+            //  [鍗℃璇婃柇] setter 閲屾嬁涓嶅埌 skillId锛岃繖閲岃ˉ涓婏紝渚� SkillBase.ReportStuckIfNeeded dump
+            _pswaSetTrueSkillId = skillConfig != null ? skillConfig.SkillID : 0;
+#endif
         }
         
         playingSkill = true;
@@ -857,6 +881,11 @@
 #if UNITY_EDITOR
     /// <summary>鍗℃璇婃柇鐢細鏆撮湶 playingSkillWithAnim 鏍囧織浣嶃��</summary>
     public bool PlayingSkillWithAnimForDebug => playingSkillWithAnim;
+
+    //  [鍗℃璇婃柇] 缁� SkillBase 鍗℃鎶ュ憡鐢細璋佹妸 playingSkillWithAnim 閿佷负 true銆佸湪鍝竴甯с��
+    public int PlayingSkillAnimOwnerSkillIdForDebug => _pswaSetTrueSkillId;
+    public int PlayingSkillAnimOwnerFrameForDebug => _pswaSetTrueFrame;
+    public string PlayingSkillAnimOwnerStackForDebug => _pswaSetTrueStack;
 #endif
 
     public bool CanStartDeath()
diff --git a/Main/System/Battle/Skill/SkillBase.Cast.cs b/Main/System/Battle/Skill/SkillBase.Cast.cs
index 14d5b8c..8d3ef90 100644
--- a/Main/System/Battle/Skill/SkillBase.Cast.cs
+++ b/Main/System/Battle/Skill/SkillBase.Cast.cs
@@ -10,6 +10,17 @@
     // 鎶�鑳介噴鏀句富閫昏緫锛氬箍鎾簨浠躲�侀珮浜洰鏍囥�佹墽琛岄噴鏀�
     public virtual void Cast()
     {
+#if UNITY_EDITOR
+        //  [鍓嶅啿璇婃柇] Cast() 鍏ュ彛锛氳褰� skillId/caster/BattleType/褰撳墠浣嶇疆/褰撳墠鏄惁杩樺湪 tween銆�
+        //  鐢ㄦ潵鍒ゆ柇鏂版妧鑳芥槸鍚﹀湪涓婁竴涓妧鑳界殑鍥炰綅 tween 杩樻病瀹屾垚鏃跺氨杩涘叆 Cast()銆�
+        {
+            Vector2 castEntryPos = (caster != null && caster.GetRectTransform() != null)
+                ? caster.GetRectTransform().anchoredPosition : Vector2.zero;
+            bool casterTweening = caster != null && caster.GetRectTransform() != null
+                && DG.Tweening.DOTween.IsTweening(caster.GetRectTransform());
+            BattleDebug.LogError($"[鍓嶅啿璇婃柇] Cast 鍏ュ彛 skillId={skillConfig?.SkillID} caster={caster?.ObjID} battleType={tagUseSkillAttack?.BattleType} castMode={skillSkinConfig?.castMode} anchoredPos={castEntryPos} casterTweening={casterTweening}");
+        }
+#endif
         // 骞挎挱鎶�鑳介噴鏀句簨浠�
         string guid = battleField.guid;
         // 鑾峰彇閲婃斁鑰呮暟鎹細Hero 浼犻�� teamHero锛孧ingge 浼犻�� null锛堝洜涓轰簨浠剁洃鍚櫒鍙鐞� Hero 鏁版嵁锛�
@@ -163,9 +174,15 @@
     // 鎵ц绉诲姩-鏂芥硶-杩斿洖搴忓垪锛氶�氱敤鐨勭Щ鍔ㄦ敾鍑绘祦绋�
     private void ExecuteMoveAndCastSequence(RectTransform target, Action onReturnComplete)
     {
+#if UNITY_EDITOR
+        BattleDebug.LogError($"[鍓嶅啿璇婃柇] ExecuteMoveAndCastSequence 寮�濮� skillId={skillConfig?.SkillID} caster={caster?.ObjID} battleType={tagUseSkillAttack?.BattleType} CastDistance={skillSkinConfig?.CastDistance} castMode={skillSkinConfig?.castMode}");
+#endif
         ShadowIllutionCreate(true);
         MoveToTarget(target, new Vector2(skillSkinConfig.CastDistance, 0), () =>
         {
+#if UNITY_EDITOR
+            BattleDebug.LogError($"[鍓嶅啿璇婃柇] 鍓嶅啿瀹屾垚 skillId={skillConfig?.SkillID} caster={caster?.ObjID} 鍑嗗 CastImpl");
+#endif
             if (skillSkinConfig.CastDistance < 9999 && skillSkinConfig.SkinllSFX2 != 0)
             {
                 battleField.soundManager.PlayEffectSound(skillSkinConfig.SkinllSFX2, false);
@@ -197,18 +214,52 @@
     // 绉诲姩鍒扮洰鏍囦綅缃細澶勭悊瑙掕壊鐨勭Щ鍔ㄥ姩鐢诲拰閫昏緫
     protected void MoveToTarget(RectTransform target, Vector2 offset, Action _onComplete = null, float speed = 750f)
     {
+#if UNITY_EDITOR
+        //  [鍓嶅啿璇婃柇] 璁板綍鍏ュ彛鍙傛暟锛欳astDistance銆乷ffset銆乻peed锛涗互鍙婂綋鍓� caster 鐨勯敋鐐逛綅缃��
+        Vector2 fromPos = caster != null && caster.GetRectTransform() != null
+            ? caster.GetRectTransform().anchoredPosition : Vector2.zero;
+        bool mttTweening = caster != null && caster.GetRectTransform() != null
+            && DG.Tweening.DOTween.IsTweening(caster.GetRectTransform());
+        BattleDebug.LogError($"[鍓嶅啿璇婃柇] MoveToTarget 鍏ュ彛 skillId={skillConfig?.SkillID} caster={caster?.ObjID} battleType={tagUseSkillAttack?.BattleType} CastDistance={skillSkinConfig?.CastDistance} offset={offset} speed={speed} fromPos={fromPos} casterTweening={mttTweening}");
+#endif
         if (skillSkinConfig.CastDistance >= 9999)
         {
+#if UNITY_EDITOR
+            BattleDebug.LogError($"[鍓嶅啿璇婃柇] CastDistance>=9999 鐩存帴璺宠繃绉诲姩 skillId={skillConfig?.SkillID} caster={caster?.ObjID}");
+#endif
             _onComplete?.Invoke();
             return;
         }
 
         caster.PlayAnimation(MotionName.run, true);
+#if UNITY_EDITOR
+        //  [鍓嶅啿璇婃柇] 璁板綍 target 鐨勫悕瀛�/涓栫晫鍧愭爣/鐖惰妭鐐� scale锛屼究浜庡畾浣嶉暅鍍忓潗鏍囩郴瀵艰嚧 offset 鏂瑰悜鍙嶈浆
+        string targetName = target != null ? target.name : "(null)";
+        Vector3 targetWorld = target != null ? target.position : Vector3.zero;
+        Vector3 targetLossyScale = target != null ? (Vector3)target.lossyScale : Vector3.one;
+        Vector2 targetAnchored = target != null ? target.anchoredPosition : Vector2.zero;
+        BattleDebug.LogError($"[鍓嶅啿璇婃柇] target淇℃伅 skillId={skillConfig?.SkillID} caster={caster?.ObjID} casterCamp={caster?.Camp} target.name={targetName} target.anchoredPos={targetAnchored} target.worldPos={targetWorld} target.lossyScale={targetLossyScale}");
+#endif
         var tweener = BattleUtility.MoveToTarget(caster.GetRectTransform(), target, offset, () =>
         {
+#if UNITY_EDITOR
+            Vector2 toPos = caster != null && caster.GetRectTransform() != null
+                ? caster.GetRectTransform().anchoredPosition : Vector2.zero;
+            BattleDebug.LogError($"[鍓嶅啿璇婃柇] MoveToTarget 瀹屾垚 skillId={skillConfig?.SkillID} caster={caster?.ObjID} toPos={toPos}");
+#endif
+            //  tween 瀹屾垚鏃舵竻闄� caster 涓婄殑 activeMoveTween 鍙ユ焺锛屾斁寮� CanCastSkillAnimation 鐨勯椄闂ㄣ��
+            if (caster != null)
+            {
+                caster.activeMoveTween = null;
+            }
             caster.PlayAnimation(MotionName.idle, true);
             _onComplete?.Invoke();
         }, speed);
+        //  璁板綍鍒� caster锛岃 CanCastSkillAnimation 鑳界簿纭瓑寰呰繖涓�涓� tween锛堣�屼笉鏄� caster 韬笂浠绘剰 tween锛夈��
+        if (caster != null)
+        {
+            caster.activeMoveTween = tweener;
+        }
         battleField.battleTweenMgr.OnPlayTween(tweener);
     }
 
@@ -225,6 +276,16 @@
     // 鏀诲嚮瀹屾垚鍚庣殑澶勭悊锛氳浆韬�佹仮澶嶇姸鎬併�佹挱鏀惧緟鏈哄姩鐢�
     protected void OnAttackFinish()
     {
+#if UNITY_EDITOR
+        //  [鍓嶅啿璇婃柇] OnAttackFinish 鍏ュ彛锛氳褰曞抚鍙峰拰褰撳墠浣嶇疆锛屽拰 Cast()/MoveToTarget 鏃ュ織瀵归綈銆�
+        {
+            Vector2 finPos = (caster != null && caster.GetRectTransform() != null)
+                ? caster.GetRectTransform().anchoredPosition : Vector2.zero;
+            bool finTweening = caster != null && caster.GetRectTransform() != null
+                && DG.Tweening.DOTween.IsTweening(caster.GetRectTransform());
+            BattleDebug.LogError($"[鍓嶅啿璇婃柇] OnAttackFinish skillId={skillConfig?.SkillID} caster={caster?.ObjID} battleType={tagUseSkillAttack?.BattleType} anchoredPos={finPos} casterTweening={finTweening}");
+        }
+#endif
         TurnBack(null, 1f);
         OnAllAttackMoveFinished();
         caster.PlayAnimation(MotionName.idle, true);
diff --git a/Main/System/Battle/Skill/SkillBase.Finish.cs b/Main/System/Battle/Skill/SkillBase.Finish.cs
index f50d207..b8758c4 100644
--- a/Main/System/Battle/Skill/SkillBase.Finish.cs
+++ b/Main/System/Battle/Skill/SkillBase.Finish.cs
@@ -190,6 +190,22 @@
         if (caster is HeroBattleObject hbo && hbo.motionBase != null)
         {
             casterAnim = $"  caster.motionBase: playingSkillWithAnim={hbo.motionBase.PlayingSkillWithAnimForDebug}";
+            //  [鍗℃璇婃柇] 褰� playingSkillWithAnim=true 浣嗘湰 skillBase 杩樻病 OnSkillStart锛�
+            //  涓�娆℃�ф妸 MotionBase 鐨勭幇鍦轰篃 dump 鍑烘潵锛氶攣鏄皝鍔犵殑 + 娲昏穬杞ㄩ亾鍒楄〃 + 鍔犻攣鏃剁殑璋冪敤鏍堛��
+            //  杩欐牱 SkillBase 鐨� 120 甯у崱姝绘姤鍛婂氨鑳界洿鎺ュ畾浣嶅埌 MotionBase 渚х殑 owner skill銆�
+            if (hbo.motionBase.PlayingSkillWithAnimForDebug)
+            {
+                int ownerSid = hbo.motionBase.PlayingSkillAnimOwnerSkillIdForDebug;
+                int ownerFrame = hbo.motionBase.PlayingSkillAnimOwnerFrameForDebug;
+                int elapsed = ownerFrame > 0 ? (UnityEngine.Time.frameCount - ownerFrame) : -1;
+                casterAnim += $"\n  MotionBase閿佹寔鏈夎��: skillId={ownerSid} setFrame={ownerFrame} 宸叉寔鏈墈elapsed}甯�";
+                casterAnim += $"\n  MotionBase鐜板満: {hbo.motionBase.DumpActiveTracksForDebug()}";
+                string ownerStack = hbo.motionBase.PlayingSkillAnimOwnerStackForDebug;
+                if (!string.IsNullOrEmpty(ownerStack))
+                {
+                    casterAnim += $"\n  MotionBase閿佸姞閿佽皟鐢ㄦ爤:\n{ownerStack}";
+                }
+            }
         }
         string skinInfo = $"  skillSkinConfig.SkillMotionName={(skillSkinConfig == null ? "null" : (string.IsNullOrEmpty(skillSkinConfig.SkillMotionName) ? "(绌�)" : skillSkinConfig.SkillMotionName))}";
         string skillEffectDump = skillEffect == null ? "  skillEffect=null" : $"  skillEffect: {skillEffect.DumpState()}";

--
Gitblit v1.8.0