From 8f983d0dab26becb6b85dbbb616fde21c3ad8f02 Mon Sep 17 00:00:00 2001
From: yyl <yyl>
Date: 星期三, 20 八月 2025 18:40:23 +0800
Subject: [PATCH] 125 【战斗】战斗系统

---
 Main/System/Battle/SkillEffect/NormalSkillEffect.cs                                          |   93 +--
 Main/System/Battle/BattleObject/BattleObjectFactory.cs                                       |    3 
 Main/System/Battle/SkillEffect/BulletCurve/BounceBulletCurve.cs                              |    2 
 Main/System/Battle/SkillEffect/BulletCurve/StraightBulletCurve.cs                            |    6 
 Main/Core/NetworkPackage/DTCFile/ServerPack/HB4_FightDefine/DTCB422_tagMCTurnFightObjDead.cs |    6 
 Main/System/Battle/Motion/MotionBase.cs                                                      |  149 ++++--
 Main/Core/NetworkPackage/ServerPack/HB4_FightDefine/HB418_tagSCObjPropertyRefreshView.cs     |    2 
 Main/Config/Configs/SkillConfig.cs                                                           |  103 ++--
 Main/System/Battle/SkillEffect/BulletCurve/BulletCurveFactory.cs                             |   10 
 Main/System/Battle/SkillEffect/SkillEffectFactory.cs                                         |   28 
 Main/System/Battle/BattleField/BattleField.cs                                                |    6 
 Main/System/Battle/BattleTweenMgr.cs                                                         |    8 
 Main/System/Battle/BattleObject/BattleObject.cs                                              |    1 
 Main/System/Battle/SkillEffect/BulletCurve/BezierBulletCurve.cs                              |    7 
 Main/Utility/EffectPenetrationBlocker.cs                                                     |   37 +
 Main/System/Battle/Skill/DirectlyHealSkill.cs                                                |   35 -
 Main/System/Battle/SkillEffect/BulletCurve/PenetrateBulletCurve.cs                           |    6 
 Main/System/Battle/BattleEffectMgr.cs                                                        |   11 
 Main/System/Team/TeamBase.cs                                                                 |    4 
 Main/Component/UI/Effect/BattleEffectPlayer.cs                                               |  111 ++++
 Main/Config/Configs/EffectConfig.cs                                                          |    8 
 Main/System/Battle/SkillEffect/BulletCurve/BulletCurve.cs                                    |    8 
 Main/System/Battle/BattleUtility.cs                                                          |  103 ++++
 Main/System/Battle/Skill/DirectlyDamageSkill.cs                                              |   46 +-
 Main/System/Battle/Skill/RebornSkill.cs                                                      |   31 -
 Main/System/Battle/SkillEffect/SkillEffect.cs                                                |   14 
 Main/System/Battle/SkillEffect/BulletSkillEffect.cs                                          |   37 +
 Main/System/Battle/RecordPlayer/RecordPlayer.cs                                              |   24 +
 Main/System/Battle/Skill/SkillBase.cs                                                        |  359 ++++++++-------
 Main/Config/Configs/HeroSkinConfig.cs                                                        |    2 
 Main/System/Battle/BattleField/RecordActions/DeathRecordAction.cs                            |   26 
 Main/Utility/UniTaskExtension.cs                                                             |   21 
 32 files changed, 794 insertions(+), 513 deletions(-)

diff --git a/Main/Component/UI/Effect/BattleEffectPlayer.cs b/Main/Component/UI/Effect/BattleEffectPlayer.cs
index 1a09695..5dc1a4b 100644
--- a/Main/Component/UI/Effect/BattleEffectPlayer.cs
+++ b/Main/Component/UI/Effect/BattleEffectPlayer.cs
@@ -60,7 +60,7 @@
 
     protected GameObject spineContainer;
 
-    protected SkeletonGraphic spineComp;
+    protected SkeletonAnimation spineComp;
     protected Spine.AnimationState spineAnimationState;
 
     public GameObjectPoolManager.GameObjectPool pool;
@@ -107,13 +107,14 @@
         }
 
         //  鍒濆鍖杝pine缁勪欢
-        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);
     }
 
     protected virtual void Clear()
@@ -149,20 +150,22 @@
 
     public virtual void Play(bool showLog = true)
     {
+
+
         if (!isInit)
-        {
-            InitComponent(showLog);
-            isInit = true;
-        }
-        else
-        {
-            //閬垮厤閲嶅鍒涘缓
-            if (!this.gameObject.activeSelf)
             {
-                this.gameObject.SetActive(true);
+                InitComponent(showLog);
+                isInit = true;
             }
-            return;
-        }
+            else
+            {
+                //閬垮厤閲嶅鍒涘缓
+                if (!this.gameObject.activeSelf)
+                {
+                    this.gameObject.SetActive(true);
+                }
+                return;
+            }
 
         if (EffectMgr.IsNotShowBySetting(effectId))
         {
@@ -194,6 +197,15 @@
             return;
         }
 
+        //  濡傛灉delay灏忎簬绛変簬0 閭d細绔嬪埢鎵ц
+        this.DelayTime(effectConfig.delayPlay, () =>
+        {
+            PlayEffectInternal();
+        });
+    }
+
+    protected void PlayEffectInternal()
+    {
         if (effectConfig.isSpine != 0)
         {
             PlaySpineEffect();
@@ -202,7 +214,6 @@
         {
             PlayUnityEffect();
         }
-        
     }
 
     protected void PlaySpineEffect()
@@ -215,18 +226,50 @@
             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.Complete -= OnSpineAnimationComplete;
         spineAnimationState.Complete += OnSpineAnimationComplete;
 
+
+        if (null == canvas)
+            canvas = GetComponentInParent<Canvas>();
+
+        // 娣诲姞鐗规晥绌块�忛樆鎸″櫒
+        blocker = spineComp.AddMissingComponent<EffectPenetrationBlocker>();
+
+        blocker.onSortingChanged = OnSortingChanged;
+
+        //  濡傛灉娌℃湁canvas鐨勮瘽 姝e父鏄洜涓轰笉鍦˙attleWin涓嬮潰鐨勮妭鐐� 鎰忔�濆氨鏄綋鍓嶆病鏈夋樉绀� 绛夊埌鍒囧洖鎴樻枟鐨勬椂鍊欏啀閫氳繃BattleField.UpdateCanvas鏉ユ洿鏂�
+        if (canvas != null)
+        {
+            blocker.SetParentCanvas(canvas);
+        }
+
+        spineComp.enabled = true;
+
         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()
@@ -268,6 +311,8 @@
         // 娣诲姞鐗规晥绌块�忛樆鎸″櫒
         blocker = effectTarget.AddMissingComponent<EffectPenetrationBlocker>();
 
+        blocker.onSortingChanged = OnSortingChanged;
+
         //  濡傛灉娌℃湁canvas鐨勮瘽 姝e父鏄洜涓轰笉鍦˙attleWin涓嬮潰鐨勮妭鐐� 鎰忔�濆氨鏄綋鍓嶆病鏈夋樉绀� 绛夊埌鍒囧洖鎴樻枟鐨勬椂鍊欏啀閫氳繃BattleField.UpdateCanvas鏉ユ洿鏂�
         if (canvas != null)
         {
@@ -278,6 +323,32 @@
 
     }
 
+    void LateUpdate()
+    {
+        if (string.IsNullOrEmpty(sortingLayer))
+        {
+            return;
+        }
+
+        OnSortingChanged(sortingLayer, sortingOrder);
+    }
+
+    public string sortingLayer;
+    public int sortingOrder;
+
+    protected void OnSortingChanged(string _sortingLayer, int _sortingOrder)
+    {
+        sortingLayer = _sortingLayer;
+        sortingOrder = _sortingOrder;
+        // 澶勭悊鎺掑簭鍙樺寲
+        var renderers = spineComp.GetComponents<Renderer>();
+        foreach (var renderer in renderers)
+        {
+            renderer.sortingLayerName = sortingLayer;
+            renderer.sortingOrder = sortingOrder;
+        }
+    }
+
     protected void OnDestroy()
     {
         if (onDestroy != null)
diff --git a/Main/Config/Configs/EffectConfig.cs b/Main/Config/Configs/EffectConfig.cs
index a5b5241..d6469e2 100644
--- a/Main/Config/Configs/EffectConfig.cs
+++ b/Main/Config/Configs/EffectConfig.cs
@@ -1,6 +1,6 @@
 锘�//--------------------------------------------------------
 //    [Author]:           YYL
-//    [  Date ]:           2025骞�8鏈�14鏃�
+//    [  Date ]:           2025骞�8鏈�19鏃�
 //--------------------------------------------------------
 
 using System.Collections.Generic;
@@ -27,6 +27,8 @@
 	public int autoDestroy;
 	public float destroyDelay;
 	public int isLoop;
+	public int frontBack;
+	public float delayPlay;
 
     public override int LoadKey(string _key)
     {
@@ -59,6 +61,10 @@
 			float.TryParse(tables[9],out destroyDelay); 
 
 			int.TryParse(tables[10],out isLoop); 
+
+			int.TryParse(tables[11],out frontBack); 
+
+			float.TryParse(tables[12],out delayPlay); 
         }
         catch (Exception exception)
         {
diff --git a/Main/Config/Configs/HeroSkinConfig.cs b/Main/Config/Configs/HeroSkinConfig.cs
index b83395d..af36b72 100644
--- a/Main/Config/Configs/HeroSkinConfig.cs
+++ b/Main/Config/Configs/HeroSkinConfig.cs
@@ -1,6 +1,6 @@
 锘�//--------------------------------------------------------
 //    [Author]:           YYL
-//    [  Date ]:           2025骞�8鏈�5鏃�
+//    [  Date ]:           2025骞�8鏈�18鏃�
 //--------------------------------------------------------
 
 using System.Collections.Generic;
diff --git a/Main/Config/Configs/SkillConfig.cs b/Main/Config/Configs/SkillConfig.cs
index d08c339..002e87f 100644
--- a/Main/Config/Configs/SkillConfig.cs
+++ b/Main/Config/Configs/SkillConfig.cs
@@ -1,6 +1,6 @@
 锘�//--------------------------------------------------------
 //    [Author]:           YYL
-//    [  Date ]:           2025骞�8鏈�7鏃�
+//    [  Date ]:           Wednesday, August 20, 2025
 //--------------------------------------------------------
 
 using System.Collections.Generic;
@@ -30,9 +30,6 @@
 	public int TagAffect;
 	public int TagCount;
 	public int HappenRate;
-	public int LastTime;
-	public int CoolDownTime;
-	public int Priority;
 	public int EffectID1;
 	public int[] EffectValues1;
 	public int EffectID2;
@@ -40,10 +37,11 @@
 	public int EffectID3;
 	public int[] EffectValues3;
 	public int ConnSkill;
+	public int CoolDownTime;
 	public int[] EnhanceSkillList;
 	public int FightPower;
 	public int StartupFrames;
-	public int ActiveFrames;
+	public int[] ActiveFrames;
 	public int RecoveryFrames;
 	public int LoopCount;
 	public int CastPosition;
@@ -61,6 +59,7 @@
 	public int EffectPos;
 	public int EffectType;
 	public string IconName;
+	public int ExplosionEffect2;
 
     public override int LoadKey(string _key)
     {
@@ -100,21 +99,15 @@
 
 			int.TryParse(tables[13],out HappenRate); 
 
-			int.TryParse(tables[14],out LastTime); 
+			int.TryParse(tables[14],out EffectID1); 
 
-			int.TryParse(tables[15],out CoolDownTime); 
-
-			int.TryParse(tables[16],out Priority); 
-
-			int.TryParse(tables[17],out EffectID1); 
-
-			if (tables[18].Contains("["))
+			if (tables[15].Contains("["))
 			{
-				EffectValues1 = JsonMapper.ToObject<int[]>(tables[18]);
+				EffectValues1 = JsonMapper.ToObject<int[]>(tables[15]);
 			}
 			else
 			{
-				string[] EffectValues1StringArray = tables[18].Trim().Split(StringUtility.splitSeparator,StringSplitOptions.RemoveEmptyEntries);
+				string[] EffectValues1StringArray = tables[15].Trim().Split(StringUtility.splitSeparator,StringSplitOptions.RemoveEmptyEntries);
 				EffectValues1 = new int[EffectValues1StringArray.Length];
 				for (int i=0;i<EffectValues1StringArray.Length;i++)
 				{
@@ -122,15 +115,15 @@
 				}
 			}
 
-			int.TryParse(tables[19],out EffectID2); 
+			int.TryParse(tables[16],out EffectID2); 
 
-			if (tables[20].Contains("["))
+			if (tables[17].Contains("["))
 			{
-				EffectValues2 = JsonMapper.ToObject<int[]>(tables[20]);
+				EffectValues2 = JsonMapper.ToObject<int[]>(tables[17]);
 			}
 			else
 			{
-				string[] EffectValues2StringArray = tables[20].Trim().Split(StringUtility.splitSeparator,StringSplitOptions.RemoveEmptyEntries);
+				string[] EffectValues2StringArray = tables[17].Trim().Split(StringUtility.splitSeparator,StringSplitOptions.RemoveEmptyEntries);
 				EffectValues2 = new int[EffectValues2StringArray.Length];
 				for (int i=0;i<EffectValues2StringArray.Length;i++)
 				{
@@ -138,15 +131,15 @@
 				}
 			}
 
-			int.TryParse(tables[21],out EffectID3); 
+			int.TryParse(tables[18],out EffectID3); 
 
-			if (tables[22].Contains("["))
+			if (tables[19].Contains("["))
 			{
-				EffectValues3 = JsonMapper.ToObject<int[]>(tables[22]);
+				EffectValues3 = JsonMapper.ToObject<int[]>(tables[19]);
 			}
 			else
 			{
-				string[] EffectValues3StringArray = tables[22].Trim().Split(StringUtility.splitSeparator,StringSplitOptions.RemoveEmptyEntries);
+				string[] EffectValues3StringArray = tables[19].Trim().Split(StringUtility.splitSeparator,StringSplitOptions.RemoveEmptyEntries);
 				EffectValues3 = new int[EffectValues3StringArray.Length];
 				for (int i=0;i<EffectValues3StringArray.Length;i++)
 				{
@@ -154,15 +147,17 @@
 				}
 			}
 
-			int.TryParse(tables[23],out ConnSkill); 
+			int.TryParse(tables[20],out ConnSkill); 
 
-			if (tables[24].Contains("["))
+			int.TryParse(tables[21],out CoolDownTime); 
+
+			if (tables[22].Contains("["))
 			{
-				EnhanceSkillList = JsonMapper.ToObject<int[]>(tables[24]);
+				EnhanceSkillList = JsonMapper.ToObject<int[]>(tables[22]);
 			}
 			else
 			{
-				string[] EnhanceSkillListStringArray = tables[24].Trim().Split(StringUtility.splitSeparator,StringSplitOptions.RemoveEmptyEntries);
+				string[] EnhanceSkillListStringArray = tables[22].Trim().Split(StringUtility.splitSeparator,StringSplitOptions.RemoveEmptyEntries);
 				EnhanceSkillList = new int[EnhanceSkillListStringArray.Length];
 				for (int i=0;i<EnhanceSkillListStringArray.Length;i++)
 				{
@@ -170,45 +165,59 @@
 				}
 			}
 
-			int.TryParse(tables[25],out FightPower); 
+			int.TryParse(tables[23],out FightPower); 
 
-			int.TryParse(tables[26],out StartupFrames); 
+			int.TryParse(tables[24],out StartupFrames); 
 
-			int.TryParse(tables[27],out ActiveFrames); 
+			if (tables[25].Contains("["))
+			{
+				ActiveFrames = JsonMapper.ToObject<int[]>(tables[25]);
+			}
+			else
+			{
+				string[] ActiveFramesStringArray = tables[25].Trim().Split(StringUtility.splitSeparator,StringSplitOptions.RemoveEmptyEntries);
+				ActiveFrames = new int[ActiveFramesStringArray.Length];
+				for (int i=0;i<ActiveFramesStringArray.Length;i++)
+				{
+					 int.TryParse(ActiveFramesStringArray[i],out ActiveFrames[i]);
+				}
+			}
 
-			int.TryParse(tables[28],out RecoveryFrames); 
+			int.TryParse(tables[26],out RecoveryFrames); 
 
-			int.TryParse(tables[29],out LoopCount); 
+			int.TryParse(tables[27],out LoopCount); 
 
-			int.TryParse(tables[30],out CastPosition); 
+			int.TryParse(tables[28],out CastPosition); 
 
-			int.TryParse(tables[31],out CastIndexNum); 
+			int.TryParse(tables[29],out CastIndexNum); 
 
-			float.TryParse(tables[32],out CastDistance); 
+			float.TryParse(tables[30],out CastDistance); 
 
-			DamageDivide = JsonMapper.ToObject<int[][]>(tables[33].Replace("(", "[").Replace(")", "]")); 
+			DamageDivide = JsonMapper.ToObject<int[][]>(tables[31].Replace("(", "[").Replace(")", "]")); 
 
-			int.TryParse(tables[34],out BulletEffectId); 
+			int.TryParse(tables[32],out BulletEffectId); 
 
-			int.TryParse(tables[35],out BulletPos); 
+			int.TryParse(tables[33],out BulletPos); 
 
-			int.TryParse(tables[36],out BulletPath); 
+			int.TryParse(tables[34],out BulletPath); 
 
-			int.TryParse(tables[37],out BulletFlyTime); 
+			int.TryParse(tables[35],out BulletFlyTime); 
 
-			int.TryParse(tables[38],out ExplosionEffectId); 
+			int.TryParse(tables[36],out ExplosionEffectId); 
 
-			int.TryParse(tables[39],out ExplosionPos); 
+			int.TryParse(tables[37],out ExplosionPos); 
 
-			SkillMotionName = tables[40];
+			SkillMotionName = tables[38];
 
-			int.TryParse(tables[41],out EffectId); 
+			int.TryParse(tables[39],out EffectId); 
 
-			int.TryParse(tables[42],out EffectPos); 
+			int.TryParse(tables[40],out EffectPos); 
 
-			int.TryParse(tables[43],out EffectType); 
+			int.TryParse(tables[41],out EffectType); 
 
-			IconName = tables[44];
+			IconName = tables[42];
+
+			int.TryParse(tables[43],out ExplosionEffect2); 
         }
         catch (Exception exception)
         {
diff --git a/Main/Core/NetworkPackage/DTCFile/ServerPack/HB4_FightDefine/DTCB422_tagMCTurnFightObjDead.cs b/Main/Core/NetworkPackage/DTCFile/ServerPack/HB4_FightDefine/DTCB422_tagMCTurnFightObjDead.cs
index 2296213..8c57293 100644
--- a/Main/Core/NetworkPackage/DTCFile/ServerPack/HB4_FightDefine/DTCB422_tagMCTurnFightObjDead.cs
+++ b/Main/Core/NetworkPackage/DTCFile/ServerPack/HB4_FightDefine/DTCB422_tagMCTurnFightObjDead.cs
@@ -6,10 +6,8 @@
 public class DTCB422_tagMCTurnFightObjDead : DtcBasic {
     public override void Done(GameNetPackBasic vNetPack) {
         base.Done(vNetPack);
-        HB422_tagMCTurnFightObjDead vNetData = vNetPack as HB422_tagMCTurnFightObjDead;
 
-        BattleField battleField = BattleManager.Instance.GetBattleField(vNetPack.packUID);
-
-        battleField.OnObjDead((int)vNetData.ObjID);
+        
+        // 鐢辨妧鑳藉幓閫氱煡鎴樺満姝讳骸 battleField.OnObjsDead(deadList)
     }
 }
diff --git a/Main/Core/NetworkPackage/ServerPack/HB4_FightDefine/HB418_tagSCObjPropertyRefreshView.cs b/Main/Core/NetworkPackage/ServerPack/HB4_FightDefine/HB418_tagSCObjPropertyRefreshView.cs
index 3d788c7..1870fae 100644
--- a/Main/Core/NetworkPackage/ServerPack/HB4_FightDefine/HB418_tagSCObjPropertyRefreshView.cs
+++ b/Main/Core/NetworkPackage/ServerPack/HB4_FightDefine/HB418_tagSCObjPropertyRefreshView.cs
@@ -6,6 +6,7 @@
 public class HB418_tagSCObjPropertyRefreshView : GameNetPackBasic {
     public uint ObjID;
     public ushort RefreshType;    // 鍚�0418鍒锋柊绫诲瀷锛屽琛�閲忋�佹�掓皵
+    public uint AttackTypes;    // 椋樺瓧绫诲瀷姹囨�伙紝鏀寔澶氱绫诲瀷骞跺瓨锛屽鏃犺闃插尽涓旀毚鍑诲悓鏃惰鏍兼尅锛屼簩杩涘埗鎴栬繍绠楁渶缁堝�硷紱0-澶辫触锛�1-鏅�氾紱2-鍥炶锛�5-鏍兼尅锛�6-鏃犺闃插尽锛�7-鏆村嚮锛�9-闂伩
     public uint Value;    // 鏇存柊鍊�
     public uint ValueEx;    // 鏇存柊鍊硷紝濡傛灉鏄ぇ鏁板�肩殑姝ゅ�间负鏁撮櫎浜块儴鍒�
     public byte DiffType;    // 鍙樺寲绫诲瀷锛�0-鍑忓皯锛�1-澧炲姞
@@ -21,6 +22,7 @@
     public override void ReadFromBytes (byte[] vBytes) {
         TransBytes (out ObjID, vBytes, NetDataType.DWORD);
         TransBytes (out RefreshType, vBytes, NetDataType.WORD);
+        TransBytes (out AttackTypes, vBytes, NetDataType.DWORD);
         TransBytes (out Value, vBytes, NetDataType.DWORD);
         TransBytes (out ValueEx, vBytes, NetDataType.DWORD);
         TransBytes (out DiffType, vBytes, NetDataType.BYTE);
diff --git a/Main/System/Battle/BattleEffectMgr.cs b/Main/System/Battle/BattleEffectMgr.cs
index 3d2899a..2c5e120 100644
--- a/Main/System/Battle/BattleEffectMgr.cs
+++ b/Main/System/Battle/BattleEffectMgr.cs
@@ -43,6 +43,17 @@
 
     public BattleEffectPlayer PlayEffect(int ObjID, int effectId, Transform parent)
     {
+        if (effectId <= 0)
+        {
+            return null;
+        }
+
+        var effectCfg = EffectConfig.Get(effectId);
+        if (null == effectCfg)
+        {
+            return null;
+        }
+
         if (!effectDict.ContainsKey(effectId))
         {
             effectDict[effectId] = new List<BattleEffectPlayer>();
diff --git a/Main/System/Battle/BattleField/BattleField.cs b/Main/System/Battle/BattleField/BattleField.cs
index 7eb387d..073df12 100644
--- a/Main/System/Battle/BattleField/BattleField.cs
+++ b/Main/System/Battle/BattleField/BattleField.cs
@@ -281,9 +281,9 @@
 
     }
 
-    public virtual void OnObjDead(int ObjID)
+    public virtual void OnObjsDead(List<HB422_tagMCTurnFightObjDead> deadPackList)
     {
-        DeathRecordAction recordAction = new DeathRecordAction(this, battleObjMgr.GetBattleObject(ObjID));
+        DeathRecordAction recordAction = new DeathRecordAction(this, deadPackList);
         recordPlayer.PlayRecord(recordAction);
     }
 
@@ -324,7 +324,7 @@
         return GetTeamNode(battleCamp, index);
     }
 
-    private RectTransform GetTeamNode(BattleCamp battleCamp, int index)
+    public RectTransform GetTeamNode(BattleCamp battleCamp, int index)
     {
         if (index < 0 || index >= battleRootNode.redTeamNodeList.Count)
         {
diff --git a/Main/System/Battle/BattleField/RecordActions/DeathRecordAction.cs b/Main/System/Battle/BattleField/RecordActions/DeathRecordAction.cs
index 58211fc..cccff52 100644
--- a/Main/System/Battle/BattleField/RecordActions/DeathRecordAction.cs
+++ b/Main/System/Battle/BattleField/RecordActions/DeathRecordAction.cs
@@ -3,12 +3,14 @@
 
 public class DeathRecordAction : RecordAction
 {
+    protected List<HB422_tagMCTurnFightObjDead> deadPackList = new List<HB422_tagMCTurnFightObjDead>();
 
-	public DeathRecordAction(BattleField _battleField, BattleObject _battleObj)
-		: base(RecordActionType.Death, _battleField, _battleObj)
-	{
-		isFinish = false;
-	}
+    public DeathRecordAction(BattleField _battleField, List<HB422_tagMCTurnFightObjDead> _deadPackList)
+        : base(RecordActionType.Death, _battleField, null)
+    {
+        isFinish = false;
+        deadPackList = _deadPackList;
+    }
 
 	public override bool IsFinished()
 	{
@@ -19,8 +21,18 @@
     public override void Run()
     {
         base.Run();
-        isFinish = true;
-        battleObject.OnDeath(OnDeathAnimationEnd);
+
+        if (!isRunOnce)
+        {
+            isRunOnce = true;
+            foreach (var deadPack in deadPackList)
+            {
+                BattleObject deadObj = battleField.battleObjMgr.GetBattleObject((int)deadPack.ObjID);
+                deadObj.OnDeath(OnDeathAnimationEnd);
+            }
+            return;
+        }
+        
     }
 
     private void OnDeathAnimationEnd()
diff --git a/Main/System/Battle/BattleObject/BattleObject.cs b/Main/System/Battle/BattleObject/BattleObject.cs
index 03eb5bc..5fd4dee 100644
--- a/Main/System/Battle/BattleObject/BattleObject.cs
+++ b/Main/System/Battle/BattleObject/BattleObject.cs
@@ -328,6 +328,7 @@
         //  澶氫竴涓獄zz鐨勪竴涓壒鏁�
 
         motionBase.PlayAnimation(MotionName.idle, true);
+        heroRectTrans.anchoredPosition = Vector2.zero;
     }
 
     public void PushDropItems(BattleDrops _battleDrops)
diff --git a/Main/System/Battle/BattleObject/BattleObjectFactory.cs b/Main/System/Battle/BattleObject/BattleObjectFactory.cs
index 9bb60eb..2653acd 100644
--- a/Main/System/Battle/BattleObject/BattleObjectFactory.cs
+++ b/Main/System/Battle/BattleObject/BattleObjectFactory.cs
@@ -47,13 +47,13 @@
 
         Debug.LogError("2 BattleObjectFactory.CreateBattleObject: Creating BattleObject for " + teamHero.ObjID + " at position " + teamHero.positionNum);
 
-
         float finalScaleRate = modelScaleRate * teamHero.modelScale;
 
         skeletonGraphic.skeletonDataAsset = skeletonDataAsset;
         skeletonGraphic.Initialize(true);
         realGO.name = battleObject.ObjID.ToString();
         realGO.transform.localScale = new Vector3(finalScaleRate, finalScaleRate, finalScaleRate);
+        (realGO.transform as RectTransform).anchoredPosition = Vector2.zero;
         battleObject.Init(realGO, teamHero, _Camp);
 
         Debug.LogError(realGO.name +  " /3 BattleObjectFactory.CreateBattleObject: Creating BattleObject for " + teamHero.ObjID + " at position " + teamHero.positionNum);
@@ -64,6 +64,7 @@
 
     public static void DestroyBattleObject(int key, BattleObject battleObj)
     {
+        Debug.LogError("BattleObject destroy");
         battleObj.Destroy();
         battleObj = null;
     }
diff --git a/Main/System/Battle/BattleTweenMgr.cs b/Main/System/Battle/BattleTweenMgr.cs
index ce43c00..182e80e 100644
--- a/Main/System/Battle/BattleTweenMgr.cs
+++ b/Main/System/Battle/BattleTweenMgr.cs
@@ -44,12 +44,12 @@
         }
 
         tweenList.Add(tween);
-        tween.OnComplete(() =>
-        {
+        tween.onComplete += () =>
+        { 
             tweenList.Remove(tween);
-        });
+        };
 
-        tween.Play();
+        // tween.Play();
     }
 
     public void HaveRest()
diff --git a/Main/System/Battle/BattleUtility.cs b/Main/System/Battle/BattleUtility.cs
index f3ecdbc..a16cf6e 100644
--- a/Main/System/Battle/BattleUtility.cs
+++ b/Main/System/Battle/BattleUtility.cs
@@ -12,21 +12,27 @@
 
     public static TweenerCore<Vector2, Vector2, DG.Tweening.Plugins.Options.VectorOptions> MoveToTarget(RectTransform transform, RectTransform target, Vector2 offset, float duration, Action onComplete = null)
     {
-        Vector3 targetWorldPos = target.TransformPoint(target.anchoredPosition + offset);
+        // 1. 鑾峰彇鐩爣鐨勬渶缁� anchoredPosition锛堝姞涓� offset锛�
+        Vector2 targetAnchoredPos = target.anchoredPosition + offset;
+        Vector3 worldAnchorPos = target.TransformPoint(targetAnchoredPos);
 
-        RectTransform parentRect = transform.parent as RectTransform;
 
-        Vector2 targetAnchoredPos;
+        // 杞崲 target 鐨� anchoredPosition 鍒� sourceParent 鐨勫潗鏍囩郴
+        Vector2 localPoint;
         RectTransformUtility.ScreenPointToLocalPointInRectangle(
-            parentRect,
-            RectTransformUtility.WorldToScreenPoint(null, targetWorldPos),
-            null,
-            out targetAnchoredPos);
+            transform,
+            RectTransformUtility.WorldToScreenPoint(CameraManager.uiCamera, worldAnchorPos),
+            CameraManager.uiCamera,
+            out localPoint);
 
         // 3. DOTween 绉诲姩
-        return transform.DOAnchorPos(targetAnchoredPos, duration)
-            .SetEase(Ease.Linear)
-            .OnComplete(() => onComplete?.Invoke());
+        var tween = transform.DOAnchorPos(localPoint, duration).SetEase(Ease.Linear);
+        tween.onComplete += () =>
+        {
+            onComplete?.Invoke();
+        };
+
+        return tween;
     }
 
     public static string DisplayDamageNum(long num, int attackType)
@@ -75,4 +81,81 @@
         return config.nums[_num - 48];
     }
 
+    /// <summary>
+    /// 淇濊瘉鎵�鏈夊垎閰嶉」鍔犺捣鏉ョ瓑浜巘otalDamage锛岄伩鍏嶅洜鏁撮櫎瀵艰嚧鐨勮宸�
+    /// </summary>
+    public static List<long> DivideDamageToList(int[] damageDivide, long totalDamage)
+    {
+        List<long> fixedDamageList = new List<long>();
+        long assigned = 0;
+        int count = damageDivide.Length;
+
+        for (int i = 0; i < count; i++)
+        {
+            long damage;
+            if (i == count - 1)
+            {
+                // 鏈�鍚庝竴涓垎閰嶉」淇涓哄墿浣�
+                damage = totalDamage - assigned;
+            }
+            else
+            {
+                damage = (totalDamage * damageDivide[i] + 5000) / 10000; // 鍥涜垗浜斿叆
+                assigned += damage;
+            }
+            fixedDamageList.Add(damage);
+        }
+        return fixedDamageList;
+    }
+
+    public static List<HB422_tagMCTurnFightObjDead> FindDeadPack(List<GameNetPackBasic> packList)
+    {
+        List<HB422_tagMCTurnFightObjDead> deadPacks = new List<HB422_tagMCTurnFightObjDead>();
+        for (int i = 0; i < packList.Count; i++)
+        {
+            var pack = packList[i];
+            //	瀵绘壘姝讳骸鍖� 鎵惧埌姝讳骸鍖呬箣鍚庤鎵炬帀钀藉寘 涓嶈兘瓒呰繃鎶�鑳藉寘
+            if (pack is HB422_tagMCTurnFightObjDead)
+            {
+                var deadPack = pack as HB422_tagMCTurnFightObjDead;
+                deadPacks.Add(deadPack);
+            }
+            else if (pack is CustomHB426CombinePack)
+            {
+                //	鎵炬浜″寘涓嶈瓒婅繃鎶�鑳藉寘
+                var combinePack = pack as CustomHB426CombinePack;
+                if (combinePack.startTag.Tag.StartsWith("Skill_"))
+                {
+                    break;
+                }
+            }
+        }
+        return deadPacks;
+    }
+
+
+    public static List<HB423_tagMCTurnFightObjReborn> FindRebornPack(List<GameNetPackBasic> packList)
+    {
+        List<HB423_tagMCTurnFightObjReborn> rebornPack = new List<HB423_tagMCTurnFightObjReborn>();
+        for (int i = 0; i < packList.Count; i++)
+        {
+            var pack = packList[i];
+            //	瀵绘壘姝讳骸鍖� 鎵惧埌姝讳骸鍖呬箣鍚庤鎵炬帀钀藉寘 涓嶈兘瓒呰繃鎶�鑳藉寘
+            if (pack is HB423_tagMCTurnFightObjReborn)
+            {
+                var deadPack = pack as HB423_tagMCTurnFightObjReborn;
+                rebornPack.Add(deadPack);
+            }
+            else if (pack is CustomHB426CombinePack)
+            {
+                //	鎵炬浜″寘涓嶈瓒婅繃鎶�鑳藉寘
+                var combinePack = pack as CustomHB426CombinePack;
+                if (combinePack.startTag.Tag.StartsWith("Skill_"))
+                {
+                    break;
+                }
+            }
+        }
+        return rebornPack;
+    }
 }
\ No newline at end of file
diff --git a/Main/System/Battle/Motion/MotionBase.cs b/Main/System/Battle/Motion/MotionBase.cs
index 99e5e3b..1e5b32f 100644
--- a/Main/System/Battle/Motion/MotionBase.cs
+++ b/Main/System/Battle/Motion/MotionBase.cs
@@ -10,7 +10,7 @@
 /// </summary>
 public class MotionBase
 {
-    public static float MotionTimeScale = 2f;
+    public static float MotionTimeScale = 1f;
 
     public static List<string> AttackMotionList = new List<string>
     {
@@ -133,88 +133,143 @@
         return currentTrackEntry;
     }
 
-    public Spine.TrackEntry PlaySkillAnimation(SkillConfig skillConfig, Action onComplete = null, Action onBeginPhaseEnd = null, Action onActivePhaseEnd = null)
+    public Spine.TrackEntry PlaySkillAnimation(SkillConfig skillConfig, SkillBase skillBase, Action _onComplete = null)
     {
+        // 鍙傛暟鏍¢獙
         if (skillConfig == null)
         {
             Debug.LogError("鎶�鑳介厤缃负绌猴紝鏃犳硶鎾斁鎶�鑳藉姩鐢�");
             return null;
         }
+        if (spineAnimationState == null || skeleton == null)
+        {
+            Debug.LogError("SkeletonGraphic鎴朅nimationState鏈垵濮嬪寲锛屾棤娉曟挱鏀炬妧鑳藉姩鐢�");
+            return null;
+        }
 
-        return PlayAnimation(skillConfig.SkillMotionName, skillConfig.StartupFrames, skillConfig.ActiveFrames, skillConfig.LoopCount,
-            onComplete, onBeginPhaseEnd, onActivePhaseEnd);
-    }
+        // 鑾峰彇鍔ㄧ敾
+        Spine.Animation anim = skeleton.Data.FindAnimation(skillConfig.SkillMotionName);
+        if (anim == null)
+        {
+            Debug.LogError($"鎵句笉鍒板姩鐢�: {skillConfig.SkillMotionName}");
+            return null;
+        }
 
-    public virtual Spine.TrackEntry PlayAnimation(
-            string animationName,
-            int loopBeginFrame,
-            int loopEndFrame,
-            int loopTimes,
-            Action _onComplete = null,
-            Action onBeginPhaseEnd = null,    // 鍓嶆憞缁撴潫鍥炶皟
-            Action onActivePhaseEnd = null    // 涓憞缁撴潫鍥炶皟
-        )
-    {
-        if (spineAnimationState == null || skeleton == null) return null;
-
-        var anim = skeleton.Data.FindAnimation(animationName);
-        if (anim == null) return null;
-
+        // 鍏抽敭甯у弬鏁�
         float fps = BattleConst.skillMotionFps;
-        float beginTime = loopBeginFrame / fps;
-        float endTime = loopEndFrame / fps;
+        float middleBeginTime = skillConfig.StartupFrames / fps;
+        int loopCount = skillConfig.LoopCount;
+        int[] activeFrames = skillConfig.ActiveFrames;
+        int activeFrameCount = activeFrames.Length;
+        float recoveryFrameTime = skillConfig.RecoveryFrames / fps;
 
-        currentTrackEntry = spineAnimationState.SetAnimation(0, anim, false);
+        // 鎾斁鍔ㄧ敾
+        var skillTrackEntry = spineAnimationState.SetAnimation(0, anim, false);
+        currentTrackEntry = skillTrackEntry;
 
+        // 浜嬩欢鐘舵��
         int curLoop = 0;
-        bool finished = false;
+        bool isFinish = false;
         bool beginPhaseTriggered = false;
+        bool finalFrameStarted = false;
+        bool finalFrameEnded = false;
+        bool middleFrameStarted = false;
+        bool[] triggeredActiveFrame = new bool[activeFrameCount];
 
+        // 鎶�鑳藉紑濮�
+        skillBase.OnSkillStart();
+
+        // 鍔ㄧ敾甯ф洿鏂板鐞�
         Spine.Unity.UpdateBonesDelegate updateLocalHandler = null;
         updateLocalHandler = (ISkeletonAnimation animated) =>
         {
-            if (finished) return;
-            var entry = currentTrackEntry;
-            if (entry == null || entry.Animation != anim)
-            {
-                skeletonGraphic.UpdateLocal -= updateLocalHandler;
-                return;
-            }
+            if (isFinish) return;
+            float trackTime = skillTrackEntry.TrackTime;
 
             // 鍓嶆憞缁撴潫锛堝彧瑙﹀彂涓�娆★級
-            if (!beginPhaseTriggered && entry.TrackTime >= beginTime)
+            if (!beginPhaseTriggered && trackTime >= middleBeginTime && curLoop == 0)
             {
                 beginPhaseTriggered = true;
-                onBeginPhaseEnd?.Invoke();
+                skillBase.OnStartSkillFrameEnd();
             }
 
-            // 涓憞缁撴潫锛堟瘡娆″埌endTime閮借Е鍙戯級
-            if (entry.TrackTime >= endTime)
+            // 涓憞寮�濮嬶紙姣忚疆loop鐨勫紑濮嬶紝鍙Е鍙戜竴娆★級
+            if (!middleFrameStarted && trackTime >= middleBeginTime && curLoop < loopCount)
             {
-                onActivePhaseEnd?.Invoke();
+                middleFrameStarted = true;
+                skillBase.OnMiddleFrameStart(curLoop);
+            }
 
-                curLoop++;
-                if (curLoop >= loopTimes)
+            // 澶氭鏀诲嚮甯цЕ鍙�
+            for (int hitIndex = 0; hitIndex < activeFrameCount; hitIndex++)
+            {
+                float activeFrameTime = activeFrames[hitIndex] / fps;
+                if (!triggeredActiveFrame[hitIndex] && trackTime >= activeFrameTime)
                 {
-                    finished = true;
-                    skeletonGraphic.UpdateLocal -= updateLocalHandler;
-                    _onComplete?.Invoke();
-                    return;
+                    skillBase.OnMiddleFrameEnd(curLoop, hitIndex);
+                    triggeredActiveFrame[hitIndex] = true;
                 }
-                entry.TrackTime = beginTime;
-                beginPhaseTriggered = false; // 閲嶇疆锛屼笅涓�杞墠鎽囧彲鍐嶆瑙﹀彂
+            }
+
+            // 鍒ゆ柇鏄惁鎵�鏈塧ctiveFrame閮藉凡瑙﹀彂锛屽噯澶囪繘鍏ヤ笅涓�杞甽oop
+            bool allTriggered = true;
+            for (int i = 0; i < activeFrameCount; i++)
+            {
+                if (!triggeredActiveFrame[i])
+                {
+                    allTriggered = false;
+                    break;
+                }
+            }
+
+            // 杩涘叆涓嬩竴杞甽oop
+            if (allTriggered && curLoop < loopCount)
+            {
+                curLoop++;
+                Array.Clear(triggeredActiveFrame, 0, activeFrameCount);
+                middleFrameStarted = false;
+
+                if (curLoop < loopCount)
+                {
+                    // 閲嶆柊璁剧疆鍒扮涓�娆$殑涓憞鏃堕棿
+                    skillTrackEntry.TrackTime = middleBeginTime;
+                    beginPhaseTriggered = false;
+                }
+                else
+                {
+                    finalFrameStarted = false;
+                    finalFrameEnded = false;
+                    // 鏀跺熬闃舵鐢卞悗缁�昏緫澶勭悊
+                }
+            }
+
+            // 鏀跺熬闃舵锛歄nFinalFrameStart 鍜� OnFinalFrameEnd
+            if (curLoop >= loopCount)
+            {
+                if (!finalFrameStarted && trackTime >= recoveryFrameTime)
+                {
+                    finalFrameStarted = true;
+                    skillBase.OnFinalFrameStart();
+                }
+                if (finalFrameStarted && !finalFrameEnded && trackTime >= recoveryFrameTime)
+                {
+                    finalFrameEnded = true;
+                    skillBase.OnFinalFrameEnd();
+                    skeletonGraphic.UpdateLocal -= updateLocalHandler;
+                    isFinish = true;
+                }
             }
         };
-        skeletonGraphic.UpdateLocal += updateLocalHandler;
 
         if (_onComplete != null && currentTrackEntry != null)
         {
             trackEntryCompleteDict[currentTrackEntry] = _onComplete;
         }
 
-        return currentTrackEntry;
+        skeletonGraphic.UpdateLocal += updateLocalHandler;
+        return skillTrackEntry;
     }
-    
+
     
     /// <summary>
     /// 璁剧疆鍔ㄧ敾浜嬩欢鐩戝惉
diff --git a/Main/System/Battle/RecordPlayer/RecordPlayer.cs b/Main/System/Battle/RecordPlayer/RecordPlayer.cs
index 74e2874..a385794 100644
--- a/Main/System/Battle/RecordPlayer/RecordPlayer.cs
+++ b/Main/System/Battle/RecordPlayer/RecordPlayer.cs
@@ -7,8 +7,11 @@
     protected BattleField battleField;
 
     private Queue<RecordAction> recordActionQueue = new Queue<RecordAction>();
-
     protected RecordAction currentRecordAction;
+
+    private bool isWaitingNextAction = false;
+    private float waitTimer = 0f;
+    private const float waitInterval = 1f;
 
     public void Init(BattleField _battleField)
     {
@@ -36,6 +39,21 @@
 
     public virtual void Run()
     {
+        // 绛夊緟涓嬩竴涓猘ction
+        if (isWaitingNextAction)
+        {
+            waitTimer += Time.deltaTime;
+            if (waitTimer >= waitInterval)
+            {
+                isWaitingNextAction = false;
+                waitTimer = 0f;
+            }
+            else
+            {
+                return;
+            }
+        }
+
         if (currentRecordAction == null)
         {
             if (recordActionQueue.Count <= 0)
@@ -53,8 +71,10 @@
         if (currentRecordAction != null && currentRecordAction.IsFinished())
         {
             Debug.LogError("record action " + currentRecordAction.GetType() + " play finished");
-
             currentRecordAction = null;
+            isWaitingNextAction = true;
+            waitTimer = 0f;
+            return;
         }
 
         if (currentRecordAction == null)
diff --git a/Main/System/Battle/Skill/DirectlyDamageSkill.cs b/Main/System/Battle/Skill/DirectlyDamageSkill.cs
index a81d548..844ecb9 100644
--- a/Main/System/Battle/Skill/DirectlyDamageSkill.cs
+++ b/Main/System/Battle/Skill/DirectlyDamageSkill.cs
@@ -4,6 +4,7 @@
 using System;
 using System.Linq;
 
+
 public class DirectlyDamageSkill : SkillBase
 {
 	protected SkillEffect skillEffect;
@@ -28,25 +29,8 @@
 		base.Run();
 	}
 
-
-	//	鎶�鑳藉姩鐢绘挱鏀惧畬姣�
-	protected override void DoSkillLogic(Action _onComplete = null)
-	{
-		// if (skillConfig.EffectId > 0)
-		// {
-		// 	// 鎾斁鎶�鑳界壒鏁�
-		// 	caster.battleField.battleEffectMgr.PlayEffect(
-		// 		caster.ObjID,
-		// 		skillConfig.EffectId,
-		// 		caster.heroGo.transform
-		// 	);
-		// }
-
-		_onComplete?.Invoke();
-	}
-
-	//	鍓嶆憞缁撴潫
-	protected override void OnStartSkillFrame()
+	//	鎶�鑳藉紑濮�
+	public override void OnSkillStart()
 	{
 		skillEffect = SkillEffectFactory.CreateSkillEffect(
 				caster,
@@ -59,10 +43,16 @@
 		}
 	}
 
+	//	鍓嶆憞缁撴潫
+	public override void OnStartSkillFrameEnd()
+	{
+		base.OnStartSkillFrameEnd();
+	}
+
 	protected override void OnHitTargets(int _hitIndex, List<HB427_tagSCUseSkill.tagSCUseSkillHurt> hitList)
 	{
 		base.OnHitTargets(_hitIndex, hitList);
-    }
+	}
 
 	protected override void OnHitEachTarget(BattleObject target, long totalDamage, List<long> damageList, ref HB427_tagSCUseSkill.tagSCUseSkillHurt hurt)
 	{
@@ -70,14 +60,22 @@
 	}
 
 
-	//  涓憞缁撴潫
-	protected override void OnActiveSkillFrame()
+	public override void OnMiddleFrameStart(int times)
 	{
-		
+		base.OnMiddleFrameStart(times);
+
+		skillEffect?.OnMiddleFrameStart(times);
+	}
+
+
+	//  涓憞缁撴潫(鍛戒腑甯�)
+	public override void OnMiddleFrameEnd(int times, int hitIndex)
+	{
+		skillEffect?.OnMiddleFrameEnd(times, hitIndex);
 	}
 
 	//	鍚庢憞缁撴潫
-	protected override void OnEndSkillFrame()
+	public override void OnFinalFrameEnd()
 	{
 
 	}
diff --git a/Main/System/Battle/Skill/DirectlyHealSkill.cs b/Main/System/Battle/Skill/DirectlyHealSkill.cs
index f8f4325..3b17992 100644
--- a/Main/System/Battle/Skill/DirectlyHealSkill.cs
+++ b/Main/System/Battle/Skill/DirectlyHealSkill.cs
@@ -28,25 +28,8 @@
 		base.Run();
 	}
 
-
-	//	鎶�鑳藉姩鐢绘挱鏀惧畬姣�
-	protected override void DoSkillLogic(Action _onComplete = null)
-	{
-		// if (skillConfig.EffectId > 0)
-		// {
-		// 	// 鎾斁鎶�鑳界壒鏁�
-		// 	caster.battleField.battleEffectMgr.PlayEffect(
-		// 		caster.ObjID,
-		// 		skillConfig.EffectId,
-		// 		caster.heroGo.transform
-		// 	);
-		// }
-
-		_onComplete?.Invoke();
-	}
-
 	//	鍓嶆憞缁撴潫
-	protected override void OnStartSkillFrame()
+	public override void OnStartSkillFrameEnd()
 	{
 		skillEffect = SkillEffectFactory.CreateSkillEffect(
 				caster,
@@ -70,15 +53,15 @@
 	}
 
 
-	//  涓憞缁撴潫
-	protected override void OnActiveSkillFrame()
-	{
+	// //  涓憞缁撴潫
+	// protected override void OnActiveSkillFrame()
+	// {
 		
-	}
+	// }
 
-	//	鍚庢憞缁撴潫
-	protected override void OnEndSkillFrame()
-	{
+	// //	鍚庢憞缁撴潫
+	// protected override void OnEndSkillFrame()
+	// {
 
-	}
+	// }
 }
\ No newline at end of file
diff --git a/Main/System/Battle/Skill/RebornSkill.cs b/Main/System/Battle/Skill/RebornSkill.cs
index 985f131..e85c175 100644
--- a/Main/System/Battle/Skill/RebornSkill.cs
+++ b/Main/System/Battle/Skill/RebornSkill.cs
@@ -25,25 +25,8 @@
 		base.Run();
 	}
 
-
-	//	鎶�鑳藉姩鐢绘挱鏀惧畬姣�
-	protected override void DoSkillLogic(Action _onComplete = null)
-	{
-		// if (skillConfig.EffectId > 0)
-		// {
-		// 	// 鎾斁鎶�鑳界壒鏁�
-		// 	caster.battleField.battleEffectMgr.PlayEffect(
-		// 		caster.ObjID,
-		// 		skillConfig.EffectId,
-		// 		caster.heroGo.transform
-		// 	);
-		// }
-
-		_onComplete?.Invoke();
-	}
-
 	//	鍓嶆憞缁撴潫
-	protected override void OnStartSkillFrame()
+	public override void OnStartSkillFrameEnd()
 	{
 		skillEffect = SkillEffectFactory.CreateSkillEffect(
 				caster,
@@ -66,16 +49,4 @@
 		base.OnHitEachTarget(target, totalDamage, damageList, ref hurt);
 	}
 
-
-	//  涓憞缁撴潫
-	protected override void OnActiveSkillFrame()
-	{
-		
-	}
-
-	//	鍚庢憞缁撴潫
-	protected override void OnEndSkillFrame()
-	{
-
-	}
 }
\ No newline at end of file
diff --git a/Main/System/Battle/Skill/SkillBase.cs b/Main/System/Battle/Skill/SkillBase.cs
index a0604ba..d74d76d 100644
--- a/Main/System/Battle/Skill/SkillBase.cs
+++ b/Main/System/Battle/Skill/SkillBase.cs
@@ -9,6 +9,8 @@
 
 public class SkillBase
 {
+	protected SkillEffect skillEffect;
+
 	protected HB427_tagSCUseSkill tagUseSkillAttack;
 
 	protected SkillConfig skillConfig;
@@ -68,7 +70,6 @@
 
 
 
-
 	public void Pause()
 	{
 		pauseState = startCounting;
@@ -80,119 +81,231 @@
 		startCounting = pauseState;
 	}
 
+
 	// 0路绉诲姩鍒拌窛绂荤洰鏍噉鐮侊紝鐨勮窛绂婚噴鏀撅紙鍙厤缃紝9999鍗冲師鍦伴噴鏀撅紝璐熸暟鍒欐槸绉诲姩鍒颁汉鐗╄儗闈紝浜虹墿瑕佽浆韬級
 	// 1路绉诲姩鍒拌窛绂婚樀瀹逛綅缃畁鐮佺殑璺濈锛堝2鍙蜂綅锛�5鍙蜂綅锛夐噴鏀撅紙鍗虫垬鍦轰腑澶绫伙級
 	public virtual void Cast()
 	{
+		Debug.LogError(GetType().Name + " Skill Cast Start");
 		//	楂樹寒鎵�鏈夋湰娆℃妧鑳界浉鍏崇殑鐩爣
 		HighLightAllTargets();
 
 		//	璺濈閰嶆垚璐熸暟瑕佽浆韬� TurnBack
-
+		Debug.LogError(GetType().Name + " Skill CastMode : " + skillConfig.castMode);
 		switch (skillConfig.castMode)
 		{
 			case SkillCastMode.Self:
-				PlayCastAnimation(() => DoSkillLogic(OnSkillFinished));
+				CastImpl();
 				break;
 			case SkillCastMode.Enemy:
-				MoveToTarget(caster.GetEnemyCamp(), skillConfig, _onComplete: () => TurnBack(() => PlayCastAnimation(() => DoSkillLogic(() => { BackToOrigin(OnSkillFinished); }))));
+				CastToEnemy();
 				break;
 			case SkillCastMode.Target:
-				// 鐩爣鏄晫鏂逛富鐩爣
-				if (tagUseSkillAttack.HurtCount <= 0)
-				{
-					Debug.LogError("鎶�鑳芥敾鍑诲寘娌℃湁鐩爣 HurtCount <= 0");
-					OnSkillFinished();
-					return;
-				}
-
-				var mainHurt = tagUseSkillAttack.HurtList[0];
-
-				BattleObject mainTarget = battleField.battleObjMgr.GetBattleObject((int)mainHurt.ObjID);
-				if (mainTarget == null)
-				{
-					Debug.LogError("鐩爣涓虹┖ mainTarget == null ObjID : " + mainHurt.ObjID);
-					OnSkillFinished();
-					return;
-				}
-				MoveToTarget(mainTarget.Camp, mainTarget, _onComplete: () => TurnBack(() => PlayCastAnimation(() => DoSkillLogic(() => { BackToOrigin(OnSkillFinished); }))));
+				CastToTarget();
 				break;
 			case SkillCastMode.Allies:
-				MoveToTarget(caster.Camp, skillConfig, _onComplete: () => TurnBack(() => PlayCastAnimation(() => DoSkillLogic(() => { BackToOrigin(OnSkillFinished); }))));
+				CastToAllies();
 				break;
 			// case SkillCastMode.DashCast:
 			// 	DashToTarget(() => BackToOrigin(OnSkillFinished));
 			// 	break;
 			default:
-				Debug.LogError("鏆傛椂涓嶆敮鎸佸叾浠栫殑鏂瑰紡閲婃斁 鏈夐渶姹傝鑱旂郴绛栧垝" + skillConfig.SkillID);
+				Debug.LogError("鏆傛椂涓嶆敮鎸佸叾浠栫殑鏂瑰紡閲婃斁 鏈夐渶姹傝鑱旂郴绛栧垝 鎶�鑳絠d:" + skillConfig.SkillID + " cast position " + skillConfig.CastPosition);
 				OnSkillFinished();
 				break;
 		}
 	}
 
-	//	杩欓噷鍏跺疄鏄妧鑳藉悗鎽囩粨鏉熺殑鍦版柟
-	protected virtual void DoSkillLogic(Action _onComplete = null)
+	protected void MoveToTarget(RectTransform target, Vector2 offset, float duration, Action onComplete = null)
 	{
-
-	}
-
-	protected TrackEntry PlayCastAnimation(Action onComplete = null)
-	{
-		// 鎾斁鏂芥硶鍔ㄤ綔
-		return caster.motionBase.PlaySkillAnimation(skillConfig, onComplete,
-				OnStartSkillFrame,//鏀诲嚮鍓嶆憞缁撴潫
-				OnActiveSkillFrame);//鏀诲嚮涓憞缁撴潫
-	}
-
-	public void MoveToTarget(BattleCamp camp, BattleObject target, float duration = 0.2f, Action _onComplete = null)
-	{
-		targetNode = battleField.GetTeamNode(camp, target);
-
-		Vector2 offset = new Vector2(skillConfig.CastDistance, 0);
-		RectTransform selfRect = caster.heroRectTrans;
-		RectTransform targetRect = targetNode;
-
-		var tweener = BattleUtility.MoveToTarget(selfRect, targetRect, offset, duration, _onComplete);
+		caster.motionBase.PlayAnimation(MotionName.run, true);
+		var tweener = BattleUtility.MoveToTarget(caster.heroRectTrans, target, offset, duration, () =>
+		{
+			caster.motionBase.PlayAnimation(MotionName.idle, true);
+			onComplete?.Invoke();
+		});
 		battleField.battleTweenMgr.OnPlayTween(tweener);
 	}
 
-	public void MoveToTarget(BattleCamp camp, SkillConfig skillCfg, float duration = 0.2f, Action _onComplete = null)
-	{
-		targetNode = battleField.GetTeamNode(camp, skillCfg);
-
-		Vector2 offset = new Vector2(skillConfig.CastDistance, 0);
-		RectTransform selfRect = caster.heroRectTrans;
-		RectTransform targetRect = targetNode;
-
-		var tweener = BattleUtility.MoveToTarget(selfRect, targetRect, offset, duration, _onComplete);
-		battleField.battleTweenMgr.OnPlayTween(tweener);
-	}
-
-	public void TurnBack(Action _onComplete)
+	protected void TurnBack(Action _onComplete, float forward)
 	{
 		if (skillConfig.CastDistance < 0)
 		{
 			//	杞韩
-			caster.heroGo.transform.localScale = new Vector3(-1, 1, 1);
+			Vector3 scale = caster.heroGo.transform.localScale;
+			scale.x = Mathf.Abs(scale.x) * forward;
+			caster.heroGo.transform.localScale = scale;
 		}
 		_onComplete?.Invoke();
 	}
 
-	public void BackToOrigin(Action _onComplete = null)
+	protected void CastToEnemy()
 	{
-		RectTransform selfRect = caster.heroRectTrans;
-		Vector2 targetAnchoredPos = Vector2.zero;
-		var tween = selfRect.DOAnchorPos(targetAnchoredPos, 0.2f)
-			.SetEase(Ease.Linear)
-			.OnComplete(() =>
-			{
-				//	杞垚姝g‘鏂瑰悜
-				caster.heroGo.transform.localScale = Vector3.one;
-				_onComplete?.Invoke();
-			});
+		const float moveTime = 0.5f;
 
-		battleField.battleTweenMgr.OnPlayTween(tween);
+		RectTransform target = battleField.GetTeamNode(caster.GetEnemyCamp(), skillConfig);
+
+		MoveToTarget(target, new Vector2(skillConfig.CastDistance, 0), moveTime, () =>
+		{
+			//	鍒颁綅缃浆韬�(涓嶄竴瀹氶潪瑕佽浆韬� 浣嗘槸娴佺▼瑕佸啓)
+			TurnBack(() =>
+			{
+				//	鍒拌揪鐩爣浣嶇疆
+				CastImpl(() =>
+				{
+					TurnBack(
+						() =>
+						{
+							//	鍥炲埌鍘熸潵鐨勪綅缃�
+							MoveToTarget(battleField.GetTeamNode(caster.Camp, caster.teamHero.positionNum), Vector2.zero, moveTime, () =>
+							{
+								TurnBack(null, 1f);
+								caster.motionBase.PlayAnimation(MotionName.idle, true);
+							});
+						}
+					, -1f);
+				});
+			}, -1f);
+		});
 	}
+
+
+
+	protected void CastToTarget()
+	{
+		// 鐩爣鏄晫鏂逛富鐩爣
+		if (tagUseSkillAttack.HurtCount <= 0)
+		{
+			Debug.LogError("鎶�鑳芥敾鍑诲寘娌℃湁鐩爣 HurtCount <= 0");
+			OnSkillFinished();
+			return;
+		}
+
+		var mainHurt = tagUseSkillAttack.HurtList[0];
+
+		BattleObject mainTarget = battleField.battleObjMgr.GetBattleObject((int)mainHurt.ObjID);
+		if (mainTarget == null)
+		{
+			Debug.LogError("鐩爣涓虹┖ mainTarget == null ObjID : " + mainHurt.ObjID);
+			OnSkillFinished();
+			return;
+		}
+		// MoveToTarget(mainTarget.Camp, mainTarget, _onComplete: () => TurnBack(() => CastImpl(() => DoSkillLogic(() => { BackToOrigin(OnSkillFinished); }))));
+	}
+
+	protected void CastToAllies()
+	{
+		// MoveToTarget(caster.Camp, skillConfig, _onComplete: () => TurnBack(() => CastImpl(() => DoSkillLogic(() => { BackToOrigin(OnSkillFinished); }))));
+	}
+
+	protected TrackEntry CastImpl(Action onComplete = null)
+	{
+		// 鎾斁鏂芥硶鍔ㄤ綔
+		return caster.motionBase.PlaySkillAnimation(skillConfig, this, onComplete);//鏀诲嚮涓憞缁撴潫
+	}
+
+	//	鎶�鑳藉紑濮�
+	public virtual void OnSkillStart()
+	{
+		skillEffect = SkillEffectFactory.CreateSkillEffect(
+				caster,
+				skillConfig,
+				tagUseSkillAttack
+			);
+		if (skillEffect != null)
+		{
+			skillEffect.Play(OnHitTargets);
+		}
+	}
+
+	//	鎶�鑳藉墠鎽囧抚缁撴潫
+	public virtual void OnStartSkillFrameEnd()
+	{
+
+	}
+
+	/// <summary>
+	/// 涓憞寮�濮� times=绗嚑娆″惊鐜� 浠�0寮�濮�
+	/// </summary>
+	/// <param name="times"></param>
+	public virtual void OnMiddleFrameStart(int times)
+	{
+
+	}
+
+	public virtual void OnMiddleFrameEnd(int times, int hitIndex)
+	{
+
+	}
+
+	/// <summary>
+	/// 鍚庢憞寮�濮�
+	/// </summary>
+	public virtual void OnFinalFrameStart()
+	{
+
+	}
+
+	/// <summary>
+	/// 鍚庢憞缁撴潫
+	/// </summary>
+	public virtual void OnFinalFrameEnd()
+	{
+
+	}
+
+
+
+	// public void MoveToTarget(BattleCamp camp, BattleObject target, float duration = 0.2f, Action _onComplete = null)
+	// {
+	// 	targetNode = battleField.GetTeamNode(camp, target);
+
+	// 	Vector2 offset = new Vector2(skillConfig.CastDistance, 0);
+	// 	RectTransform selfRect = caster.heroRectTrans;
+	// 	RectTransform targetRect = targetNode;
+
+	// 	var tweener = BattleUtility.MoveToTarget(selfRect, targetRect, offset, duration, _onComplete);
+	// 	battleField.battleTweenMgr.OnPlayTween(tweener);
+	// }
+
+	// public void MoveToTarget(BattleCamp camp, SkillConfig skillCfg, float duration = 0.2f, Action _onComplete = null)
+	// {
+	// 	targetNode = battleField.GetTeamNode(camp, skillCfg);
+
+	// 	Vector2 offset = new Vector2(skillConfig.CastDistance, 0);
+	// 	RectTransform selfRect = caster.heroRectTrans;
+	// 	RectTransform targetRect = targetNode;
+
+	// 	var tweener = BattleUtility.MoveToTarget(selfRect, targetRect, offset, duration, _onComplete);
+	// 	battleField.battleTweenMgr.OnPlayTween(tweener);
+	// }
+
+	// public void TurnBack(Action _onComplete)
+	// {
+	// 	if (skillConfig.CastDistance < 0)
+	// 	{
+	// 		//	杞韩
+	// 		caster.heroGo.transform.localScale = new Vector3(-1, 1, 1);
+	// 	}
+	// 	_onComplete?.Invoke();
+	// }
+
+	// public void BackToOrigin(Action _onComplete = null)
+	// {
+	// 	RectTransform selfRect = caster.heroRectTrans;
+	// 	Vector2 targetAnchoredPos = Vector2.zero;
+	// 	var tween = selfRect.DOAnchorPos(targetAnchoredPos, 0.2f)
+	// 		.SetEase(Ease.Linear);
+
+	// 	tween.onComplete += () =>
+	// 	{
+	// 		//	杞垚姝g‘鏂瑰悜
+	// 		caster.heroGo.transform.localScale = Vector3.one;
+	// 		_onComplete?.Invoke();
+	// 	};
+
+	// 	battleField.battleTweenMgr.OnPlayTween(tween);
+	// }
 
 	protected void HighLightAllTargets()
 	{
@@ -225,7 +338,7 @@
 			long totalDamage = GeneralDefine.GetFactValue(hurt.HurtHP, hurt.HurtHPEx);
 
 			// 淇濊瘉鎵�鏈夊垎閰嶉」鍔犺捣鏉ョ瓑浜巘otalDamage锛岄伩鍏嶅洜鏁撮櫎瀵艰嚧鐨勮宸�
-			List<long> damageList = DivideDamageToList(damageDivide, totalDamage);
+			List<long> damageList = BattleUtility.DivideDamageToList(damageDivide, totalDamage);
 
 			OnHitEachTarget(target, totalDamage, damageList, ref hurt);
 		}
@@ -235,7 +348,7 @@
 
 	protected void HandleDead()
 	{
-		var deadPackList = FindDeadPack();
+		var deadPackList = BattleUtility.FindDeadPack(packList);
 		CheckAfterDeadhPack();
 
 		// 澶勭悊鎺夎惤鍖� 鎻愬墠distribute涔嬪悗 PackManager鎵嶆湁鎺夎惤鐗� 鎵�浠ヤ笉璺焌ssignexp涓�鏍穌istribute
@@ -276,13 +389,14 @@
 		}
 
 		// 鍒嗗彂姝讳骸鍖�
+		battleField.OnObjsDead(deadPackList);
 		foreach (var deadPack in deadPackList)
 		{
-			PackageRegedit.Distribute(deadPack);
 			packList.Remove(deadPack);
 		}
 		deadPackList.Clear();
 	}
+
 
 
 	// 鍒嗛厤鎺夎惤
@@ -327,32 +441,7 @@
 		return expAssign;
 	}
 
-	/// <summary>
-	/// 淇濊瘉鎵�鏈夊垎閰嶉」鍔犺捣鏉ョ瓑浜巘otalDamage锛岄伩鍏嶅洜鏁撮櫎瀵艰嚧鐨勮宸�
-	/// </summary>
-	protected List<long> DivideDamageToList(int[] damageDivide, long totalDamage)
-	{
-		List<long> fixedDamageList = new List<long>();
-		long assigned = 0;
-		int count = damageDivide.Length;
 
-		for (int i = 0; i < count; i++)
-		{
-			long damage;
-			if (i == count - 1)
-			{
-				// 鏈�鍚庝竴涓垎閰嶉」淇涓哄墿浣�
-				damage = totalDamage - assigned;
-			}
-			else
-			{
-				damage = (totalDamage * damageDivide[i] + 5000) / 10000; // 鍥涜垗浜斿叆
-				assigned += damage;
-			}
-			fixedDamageList.Add(damage);
-		}
-		return fixedDamageList;
-	}
 
 	protected virtual void OnHitEachTarget(BattleObject target, long totalDamage, List<long> damageList, ref HB427_tagSCUseSkill.tagSCUseSkillHurt hurt)
 	{
@@ -368,57 +457,6 @@
 				target.heroGo.transform
 			);
 		}
-	}
-
-	protected HB423_tagMCTurnFightObjReborn FindRebornPack(BattleObject target)
-	{
-		HB423_tagMCTurnFightObjReborn rebornPack = null;
-		for (int i = 0; i < packList.Count; i++)
-		{
-			var pack = packList[i];
-			if (pack is HB423_tagMCTurnFightObjReborn)
-			{
-				rebornPack = pack as HB423_tagMCTurnFightObjReborn;
-				if (rebornPack.ObjID == target.ObjID)
-				{
-					return rebornPack;
-				}
-			}
-			else if (pack is CustomHB426CombinePack)
-			{
-				var combinePack = pack as CustomHB426CombinePack;
-				if (combinePack.startTag.Tag.StartsWith("Skill_"))
-				{
-					break; // 鎵惧埌鎶�鑳藉寘灏变笉闇�瑕佸啀澶勭悊浜�
-				}
-			}
-		}
-		return null;
-	}
-
-	protected List<HB422_tagMCTurnFightObjDead> FindDeadPack()
-	{
-		List<HB422_tagMCTurnFightObjDead> deadPacks = new List<HB422_tagMCTurnFightObjDead>();
-		for (int i = 0; i < packList.Count; i++)
-		{
-			var pack = packList[i];
-			//	瀵绘壘姝讳骸鍖� 鎵惧埌姝讳骸鍖呬箣鍚庤鎵炬帀钀藉寘 涓嶈兘瓒呰繃鎶�鑳藉寘
-			if (pack is HB422_tagMCTurnFightObjDead)
-			{
-				var deadPack = pack as HB422_tagMCTurnFightObjDead;
-				deadPacks.Add(deadPack);
-			}
-			else if (pack is CustomHB426CombinePack)
-			{
-				//	鎵炬浜″寘涓嶈瓒婅繃鎶�鑳藉寘
-				var combinePack = pack as CustomHB426CombinePack;
-				if (combinePack.startTag.Tag.StartsWith("Skill_"))
-				{
-					break;
-				}
-			}
-		}
-		return deadPacks;
 	}
 
 	protected void CheckAfterDeadhPack()
@@ -487,7 +525,8 @@
 
 	public void OnSkillFinished()
 	{
-		while (packList.Count > 0)
+		Debug.LogError(GetType().Name + " Skill Finished");
+		if (packList.Count > 0)
 		{
 			var pack = packList[0];
 			packList.RemoveAt(0);
@@ -506,21 +545,5 @@
 		}
 
 		isFinished = true;
-	}
-	
-
-	protected virtual void OnActiveSkillFrame()
-	{
-
-	}
-
-	protected virtual void OnStartSkillFrame()
-	{
-
-	}
-
-	protected virtual void OnEndSkillFrame()
-	{
-		
 	}
 }
\ No newline at end of file
diff --git a/Main/System/Battle/SkillEffect/BulletCurve/BezierBulletCurve.cs b/Main/System/Battle/SkillEffect/BulletCurve/BezierBulletCurve.cs
index d624c99..d1ab419 100644
--- a/Main/System/Battle/SkillEffect/BulletCurve/BezierBulletCurve.cs
+++ b/Main/System/Battle/SkillEffect/BulletCurve/BezierBulletCurve.cs
@@ -8,8 +8,9 @@
     private Vector2 end;
     private Vector2 control;
 
-    public BezierBulletCurve(BattleObject caster, SkillConfig skillConfig, BattleEffectPlayer effectPlayer, RectTransform target, Action<int, List<HB427_tagSCUseSkill.tagSCUseSkillHurt>> onHit)
-        : base(caster, skillConfig, effectPlayer, target, onHit) { }
+    public BezierBulletCurve(BattleObject caster, SkillConfig skillConfig, BattleEffectPlayer effectPlayer,
+        RectTransform target, HB427_tagSCUseSkill tagUseSkillAttack, Action<int, List<HB427_tagSCUseSkill.tagSCUseSkillHurt>> onHit)
+        : base(caster, skillConfig, effectPlayer, target, tagUseSkillAttack, onHit) { }
 
     public override void Reset()
     {
@@ -34,7 +35,7 @@
         if (t >= 1f)
         {
             finished = true;
-            onHit?.Invoke(0, null);
+            onHit?.Invoke(0, hurts);
         }
     }
 }
\ No newline at end of file
diff --git a/Main/System/Battle/SkillEffect/BulletCurve/BounceBulletCurve.cs b/Main/System/Battle/SkillEffect/BulletCurve/BounceBulletCurve.cs
index 8b461cd..32f90d1 100644
--- a/Main/System/Battle/SkillEffect/BulletCurve/BounceBulletCurve.cs
+++ b/Main/System/Battle/SkillEffect/BulletCurve/BounceBulletCurve.cs
@@ -16,7 +16,7 @@
 
     public BounceBulletCurve(BattleObject caster, SkillConfig skillConfig, BattleEffectPlayer effectPlayer,
         RectTransform target, HB427_tagSCUseSkill tagUseSkillAttack, Action<int, List<HB427_tagSCUseSkill.tagSCUseSkillHurt>> onHit)
-        : base(caster, skillConfig, effectPlayer, target, onHit)
+        : base(caster, skillConfig, effectPlayer, target, tagUseSkillAttack, onHit)
     {
         this.hurtList = new List<HB427_tagSCUseSkill.tagSCUseSkillHurt>(tagUseSkillAttack.HurtList);
     }
diff --git a/Main/System/Battle/SkillEffect/BulletCurve/BulletCurve.cs b/Main/System/Battle/SkillEffect/BulletCurve/BulletCurve.cs
index 7e7bf2b..7e315c8 100644
--- a/Main/System/Battle/SkillEffect/BulletCurve/BulletCurve.cs
+++ b/Main/System/Battle/SkillEffect/BulletCurve/BulletCurve.cs
@@ -1,5 +1,6 @@
 using System;
 using System.Collections.Generic;
+using System.Linq;
 using UnityEngine;
 
 public class BulletCurve
@@ -15,9 +16,9 @@
     protected float duration = 0f;
     protected float elapsed = 0f;
 
-    public BulletCurve() { }
+    protected List<HB427_tagSCUseSkill.tagSCUseSkillHurt> hurts = new List<HB427_tagSCUseSkill.tagSCUseSkillHurt>();
 
-    public BulletCurve(BattleObject caster, SkillConfig skillConfig, BattleEffectPlayer bulletEffect, RectTransform target, Action<int, List<HB427_tagSCUseSkill.tagSCUseSkillHurt>> onHit)
+    public BulletCurve(BattleObject caster, SkillConfig skillConfig, BattleEffectPlayer bulletEffect, RectTransform target, HB427_tagSCUseSkill tagUseSkillAttack, Action<int, List<HB427_tagSCUseSkill.tagSCUseSkillHurt>> onHit)
     {
         this.caster = caster;
         this.skillConfig = skillConfig;
@@ -25,6 +26,7 @@
         this.target = target;
         this.onHit = onHit;
         this.bulletTrans = bulletEffect.transform as RectTransform;
+        this.hurts = tagUseSkillAttack.HurtList.ToList();
     }
 
     public virtual void Reset()
@@ -55,7 +57,7 @@
     protected virtual void ReachTarget()
     {
         finished = true;
-        onHit?.Invoke(0, null);
+        onHit?.Invoke(0, hurts);
         caster.battleField.battleEffectMgr.RemoveEffect(skillConfig.BulletEffectId, bulletEffect);
     }
 
diff --git a/Main/System/Battle/SkillEffect/BulletCurve/BulletCurveFactory.cs b/Main/System/Battle/SkillEffect/BulletCurve/BulletCurveFactory.cs
index 4dc0b0e..1b14989 100644
--- a/Main/System/Battle/SkillEffect/BulletCurve/BulletCurveFactory.cs
+++ b/Main/System/Battle/SkillEffect/BulletCurve/BulletCurveFactory.cs
@@ -21,15 +21,15 @@
         switch (skillConfig.BulletPath)
         {
             case 1: // 鐩寸嚎娑堝け浜庣洰鏍�
-                return new StraightBulletCurve(caster, skillConfig, bulletEffect, target, onHit);
+                return new StraightBulletCurve(caster, skillConfig, bulletEffect, target, tagUseSkillAttack, onHit);
             case 2: // 鐩寸嚎璐┛娑堝け鍦ㄥ睆骞曞
-                return new PenetrateBulletCurve(caster, skillConfig, bulletEffect, target, onHit);
+                return new PenetrateBulletCurve(caster, skillConfig, bulletEffect, target, tagUseSkillAttack, onHit);
             case 3: // 鎶涚墿绾垮姬绾�
-                return new BezierBulletCurve(caster, skillConfig, bulletEffect, target, onHit);
+                return new BezierBulletCurve(caster, skillConfig, bulletEffect, target, tagUseSkillAttack, onHit);
             case 4: // 寮瑰皠
-                return new BounceBulletCurve(caster, skillConfig, bulletEffect, target, tagUseSkillAttack,onHit);
+                return new BounceBulletCurve(caster, skillConfig, bulletEffect, target, tagUseSkillAttack, onHit);
             default:
-                return new BulletCurve(caster, skillConfig, bulletEffect, target, onHit);
+                return new BulletCurve(caster, skillConfig, bulletEffect, target, tagUseSkillAttack, onHit);
         }
     }
 }
\ No newline at end of file
diff --git a/Main/System/Battle/SkillEffect/BulletCurve/PenetrateBulletCurve.cs b/Main/System/Battle/SkillEffect/BulletCurve/PenetrateBulletCurve.cs
index d05a266..ade785a 100644
--- a/Main/System/Battle/SkillEffect/BulletCurve/PenetrateBulletCurve.cs
+++ b/Main/System/Battle/SkillEffect/BulletCurve/PenetrateBulletCurve.cs
@@ -9,8 +9,8 @@
     private Vector2 outPos;     // 灞忓箷澶栧欢闀跨偣锛堟湰鍦板潗鏍囷級
     private bool hitTriggered = false; // 鏄惁宸茶Е鍙憃nHit
 
-    public PenetrateBulletCurve(BattleObject caster, SkillConfig skillConfig, BattleEffectPlayer effectPlayer, RectTransform target, Action<int, List<HB427_tagSCUseSkill.tagSCUseSkillHurt>> onHit)
-        : base(caster, skillConfig, effectPlayer, target, onHit) { }
+    public PenetrateBulletCurve(BattleObject caster, SkillConfig skillConfig, BattleEffectPlayer effectPlayer, RectTransform target, HB427_tagSCUseSkill tagUseSkillAttack, Action<int, List<HB427_tagSCUseSkill.tagSCUseSkillHurt>> onHit)
+        : base(caster, skillConfig, effectPlayer, target, tagUseSkillAttack, onHit) { }
 
     /// <summary>
     /// 鍒濆鍖栧脊閬撳弬鏁�
@@ -51,7 +51,7 @@
             if (!hitTriggered)
             {
                 hitTriggered = true;
-                onHit?.Invoke(0, null);
+                onHit?.Invoke(0, hurts);
             }
         }
         bulletTrans.anchoredPosition = pos;
diff --git a/Main/System/Battle/SkillEffect/BulletCurve/StraightBulletCurve.cs b/Main/System/Battle/SkillEffect/BulletCurve/StraightBulletCurve.cs
index 8efd581..942c0a5 100644
--- a/Main/System/Battle/SkillEffect/BulletCurve/StraightBulletCurve.cs
+++ b/Main/System/Battle/SkillEffect/BulletCurve/StraightBulletCurve.cs
@@ -7,8 +7,8 @@
     private Vector2 start;
     private Vector2 end;
 
-    public StraightBulletCurve(BattleObject caster, SkillConfig skillConfig, BattleEffectPlayer bulletEffect, RectTransform target, Action<int, List<HB427_tagSCUseSkill.tagSCUseSkillHurt>> onHit)
-        : base(caster, skillConfig, bulletEffect, target, onHit) { }
+    public StraightBulletCurve(BattleObject caster, SkillConfig skillConfig, BattleEffectPlayer bulletEffect, RectTransform target, HB427_tagSCUseSkill tagUseSkillAttack, Action<int, List<HB427_tagSCUseSkill.tagSCUseSkillHurt>> onHit)
+        : base(caster, skillConfig, bulletEffect, target, tagUseSkillAttack, onHit) { }
 
     public override void Reset()
     {
@@ -32,7 +32,7 @@
         if (t >= 1f)
         {
             finished = true;
-            onHit?.Invoke(0, null);
+            onHit?.Invoke(0, hurts);
         }
     }
 }
\ No newline at end of file
diff --git a/Main/System/Battle/SkillEffect/BulletSkillEffect.cs b/Main/System/Battle/SkillEffect/BulletSkillEffect.cs
index 10e146f..1b1b239 100644
--- a/Main/System/Battle/SkillEffect/BulletSkillEffect.cs
+++ b/Main/System/Battle/SkillEffect/BulletSkillEffect.cs
@@ -23,6 +23,7 @@
 
     public override void Play(Action<int, List<HB427_tagSCUseSkill.tagSCUseSkillHurt>> _onHit)
     {
+        base.Play(_onHit);
         //  寮瑰皠 鍙﹀鐨勫仛娉曚簡
         if (skillConfig.effectType == SkillEffectType.Bullet && skillConfig.BulletPath == 4)
         {
@@ -33,14 +34,14 @@
                 Debug.LogError("鐩爣涓虹┖ target == null ObjId : " + hurt.ObjID);
                 return;
             }
-            ShotToTarget(targetObject, _onHit);
+            ShotToTarget(targetObject);
         }
-        //  鏅�氱殑鍋氭硶
+        //  鏅�氱殑鍋氭硶 鍖哄垎鎵撳悜闃佃惀鎴栬�呮墦鍚戜釜浣�
         else
         {
             Action<int, List<HB427_tagSCUseSkill.tagSCUseSkillHurt>> onHitFormation = (_hitIndex, _hurtList) =>
             {
-                _onHit?.Invoke(_hitIndex, tagUseSkillAttack.HurtList.ToList());
+                onHit?.Invoke(_hitIndex, tagUseSkillAttack.HurtList.ToList());
             };
             switch (skillConfig.castMode)
             {
@@ -63,7 +64,7 @@
                             continue;
                         }
 
-                        ShotToTarget(target, _onHit);
+                        ShotToTarget(target);
                     }
                     break;
                 case SkillCastMode.Allies:
@@ -102,30 +103,48 @@
                 }
 
                 caster.battleField.battleEffectMgr.PlayEffect(targetObj.ObjID, skillConfig.ExplosionEffectId, targetObj.heroGo.transform);
+                caster.battleField.battleEffectMgr.PlayEffect(targetObj.ObjID, skillConfig.ExplosionEffect2, targetObj.heroGo.transform);
             }
 
-            // caster.battleField.battleEffectMgr.PlayEffect(caster.ObjID, skillConfig.ExplosionEffectId, target);
         });
 
         bulletCurves.Add(bulletCurve);
 
     }
 
-    protected void ShotToTarget(BattleObject target, Action<int, List<HB427_tagSCUseSkill.tagSCUseSkillHurt>> _onHit)
+    protected void ShotToTarget(BattleObject target)
     {
-        BattleEffectPlayer effectPlayer = caster.battleField.battleEffectMgr.PlayEffect(caster.ObjID, skillConfig.BulletEffectId, caster.effectNode);
+        BattleEffectPlayer effectPlayer = caster.battleField.battleEffectMgr.PlayEffect(caster.ObjID, skillConfig.BulletEffectId, caster.heroRectTrans);
         RectTransform effectTrans = effectPlayer.transform as RectTransform;
 
         var bulletCurve = BulletCurveFactory.CreateBulletCurve(caster, skillConfig, effectPlayer, target.heroRectTrans, tagUseSkillAttack, (index, hitList) =>
         {
-            //  鍑讳腑灏遍攢姣佸瓙寮� 瀛愬脊涓嶉渶瑕佽嚜鍔ㄩ攢姣� 閰嶇疆琛ㄩ噷autoDestroy涓篺alse
+            // 琛ㄧ幇瀛愬脊椋炶鍒扮洰鏍囦綅缃�
+            onHit?.Invoke(index, hitList);
+
+            // 鍑讳腑灏遍攢姣佸瓙寮�
             caster.battleField.battleEffectMgr.RemoveEffect(skillConfig.BulletEffectId, effectPlayer);
-            _onHit?.Invoke(index, hitList);
+            // 鎾斁瀛愬脊鐖嗙偢鐗规晥
+
+            foreach (var hurt in hitList)
+            {
+                BattleObject targetObj = caster.battleField.battleObjMgr.GetBattleObject((int)hurt.ObjID);
+                if (targetObj == null)
+                {
+                    Debug.LogError("鐩爣涓虹┖ target == null ObjId : " + hurt.ObjID);
+                    continue;
+                }
+
+                caster.battleField.battleEffectMgr.PlayEffect(targetObj.ObjID, skillConfig.ExplosionEffectId, targetObj.heroGo.transform);
+                caster.battleField.battleEffectMgr.PlayEffect(targetObj.ObjID, skillConfig.ExplosionEffect2, targetObj.heroGo.transform);
+            }
         });
 
         bulletCurves.Add(bulletCurve);
     }
 
+
+
     public override void Run()
     {
         foreach (var bulletCurve in bulletCurves)
diff --git a/Main/System/Battle/SkillEffect/NormalSkillEffect.cs b/Main/System/Battle/SkillEffect/NormalSkillEffect.cs
index 0e8d860..369704d 100644
--- a/Main/System/Battle/SkillEffect/NormalSkillEffect.cs
+++ b/Main/System/Battle/SkillEffect/NormalSkillEffect.cs
@@ -14,75 +14,48 @@
     public NormalSkillEffect(SkillConfig _skillConfig, BattleObject _caster, HB427_tagSCUseSkill _tagUseSkillAttack)
         : base(_skillConfig, _caster, _tagUseSkillAttack)
     {
-        
+
     }
 
-
+    //  鎶�鑳藉姩浣滅涓�甯�
+    //  涓嶇敤鐞嗕細鍥炶皟
     public override void Play(Action<int, List<HB427_tagSCUseSkill.tagSCUseSkillHurt>> _onHit)
     {
-
-        // // 鐗规晥鐐稿紑鍦ㄩ樀瀹圭殑涓棿鐨勫洖璋�
-        // Action<int, List<HB427_tagSCUseSkill.tagSCUseSkillHurt>> onHitLineUpCenter = (_hitIndex, _hurtList) =>
-        // {
-        //     _onHit?.Invoke(_hitIndex, tagUseSkillAttack.HurtList.ToList());
-        // };
-
-        // if (skillConfig.effectAnchor == SkillEffectAnchor.Caster)
-        // {
-        //     CastInTarget(caster.heroGo.transform as RectTransform, onHitLineUpCenter);
-        // }
-        // else if (skillConfig.effectAnchor == SkillEffectAnchor.Target)
-        // {
-        //     if (tagUseSkillAttack == null || tagUseSkillAttack.HurtList.Length <= 0)
-        //     {
-        //         Debug.LogError("娌℃湁鐩爣 tagUseSkillAttack.HurtList.Length <= 0");
-        //         _onHit?.Invoke(0, default);
-        //         return;
-        //     }
-
-        //     foreach (var hurt in tagUseSkillAttack.HurtList)
-        //     {
-        //         BattleObject target = caster.battleField.battleObjMgr.GetBattleObject((int)hurt.ObjID);
-        //         if (target == null)
-        //         {
-        //             Debug.LogError("鐗规晥鐩爣涓虹┖ target == null ObjId : " + hurt.ObjID);
-        //             continue;
-        //         }
-
-        //         CastInTarget(target.heroGo.transform as RectTransform, (index, list) => _onHit(0, new List<HB427_tagSCUseSkill.tagSCUseSkillHurt>() { hurt }));
-        //     }
-        // }
-        // else if (skillConfig.effectAnchor == SkillEffectAnchor.AlliesCenter)
-        // {
-        //     CastInTarget(caster.battleField.GetTeamNode(caster.Camp), onHitLineUpCenter);
-        // }
-        // else if (skillConfig.effectAnchor == SkillEffectAnchor.EnemiesCenter)
-        // {
-        //     CastInTarget(caster.battleField.GetTeamNode(caster.Camp == BattleCamp.Blue ? BattleCamp.Red : BattleCamp.Blue), onHitLineUpCenter);
-        // }
-        // else
-        // {
-        //     Debug.LogError("鏈煡鐨勬妧鑳界壒鏁堥敋鐐圭被鍨�: " + skillConfig.effectAnchor);
-        // }
+        // 鎾斁鎶�鑳界壒鏁�
+        BattleEffectPlayer battleEffectPlayer = caster.battleField.battleEffectMgr.PlayEffect(
+            caster.ObjID,
+            skillConfig.EffectId,
+            caster.heroGo.transform
+        );
     }
 
-    protected void CastInTarget(RectTransform target, Action<int, List<HB427_tagSCUseSkill.tagSCUseSkillHurt>> _onHit)
-    {
-        // EffectPlayer effectPlayer = caster.battleField.battleEffectMgr.PlayEffect(caster.ObjID, skillConfig.EffectId, caster.effectNode);
-
-        // RectTransform effectTrans = effectPlayer.transform as RectTransform;
-
-        // _onHit?.Invoke(0, null);
-
-        // //  閿�姣佽嚜韬笂鐨勭壒鏁堝簲璇ユ槸绛夌壒鏁堟挱鏀惧畬姣曚箣鍚�
-        // // caster.battleField.battleEffectMgr.RemoveEffect(skillConfig.EffectId, effectPlayer);
-        // //  鎾斁鍙楀嚮鐗规晥
-        // caster.battleField.battleEffectMgr.PlayEffect(caster.ObjID, skillConfig.ExplotionEffectId, target);
-
-    }
 
     public override void Run()
     {
+        base.Run();
+    }
 
+    public override void OnMiddleFrameEnd(int times, int hitIndex)
+    {
+        for (int i = 0; i < tagUseSkillAttack.HurtList.Length; i++)
+        {
+            var hurt = tagUseSkillAttack.HurtList[i];
+            BattleObject target = caster.battleField.battleObjMgr.GetBattleObject((int)hurt.ObjID);
+            if (target == null)
+            {
+                Debug.LogError("鐗规晥鐩爣涓虹┖ target == null ObjId : " + hurt.ObjID);
+                continue;
+            }
+
+            caster.battleField.battleEffectMgr.PlayEffect(target.ObjID, skillConfig.ExplosionEffectId, target.heroGo.transform);
+            caster.battleField.battleEffectMgr.PlayEffect(target.ObjID, skillConfig.ExplosionEffect2, target.heroGo.transform);
+        }
+        
+        onHit?.Invoke(hitIndex, tagUseSkillAttack.HurtList.ToList());
+    }
+
+    public override void OnMiddleFrameStart(int times)
+    {
+        
     }
 }
\ No newline at end of file
diff --git a/Main/System/Battle/SkillEffect/SkillEffect.cs b/Main/System/Battle/SkillEffect/SkillEffect.cs
index b6c41e1..9bd7c00 100644
--- a/Main/System/Battle/SkillEffect/SkillEffect.cs
+++ b/Main/System/Battle/SkillEffect/SkillEffect.cs
@@ -8,6 +8,8 @@
     protected BattleObject caster;
     protected HB427_tagSCUseSkill tagUseSkillAttack;// 鐩爣鍒楄〃
 
+    protected Action<int, List<HB427_tagSCUseSkill.tagSCUseSkillHurt>> onHit;
+
     public SkillEffect(SkillConfig _skillConfig, BattleObject _caster, HB427_tagSCUseSkill _tagUseSkillAttack)
     {
         skillConfig = _skillConfig;
@@ -18,11 +20,21 @@
     //  
     public virtual void Play(Action<int, List<HB427_tagSCUseSkill.tagSCUseSkillHurt>> _onHit)
     {
-
+        onHit = _onHit;
     }
 
     public virtual void Run()
     {
 
     }
+
+    public virtual void OnMiddleFrameEnd(int times, int hitIndex)
+    {
+        
+    }
+
+    public virtual void OnMiddleFrameStart(int times)
+    {
+        
+    }
 }
\ No newline at end of file
diff --git a/Main/System/Battle/SkillEffect/SkillEffectFactory.cs b/Main/System/Battle/SkillEffect/SkillEffectFactory.cs
index 7f6866d..39d5375 100644
--- a/Main/System/Battle/SkillEffect/SkillEffectFactory.cs
+++ b/Main/System/Battle/SkillEffect/SkillEffectFactory.cs
@@ -6,20 +6,20 @@
 {
     public static SkillEffect CreateSkillEffect(BattleObject caster, SkillConfig skillConfig, HB427_tagSCUseSkill tagUseSkillAttack)
     {
-        // switch (skillConfig.effectType)
-        // {
-        //     case SkillEffectType.Bullet:
-        //         return new BulletSkillEffect(skillConfig, caster, tagUseSkillAttack);
-        //     case SkillEffectType.Direct:
-        //         return new NormalSkillEffect(skillConfig, caster, tagUseSkillAttack);
-        //     // case SkillEffectType.BuffEffect:
-        //     //     return new BuffSkillEffect(skillConfig, caster, targets);
-        //     // case SkillEffectType.StageEffect:
-        //     //     return new StageSkillEffect(skillConfig, caster, targets);
-        //     default:
-        //         UnityEngine.Debug.LogError("Unknown Skill Effect Type");
-        //         break;
-        // }
+        switch (skillConfig.effectType)
+        {
+            case SkillEffectType.Bullet:
+                return new BulletSkillEffect(skillConfig, caster, tagUseSkillAttack);
+            case SkillEffectType.Direct:
+                return new NormalSkillEffect(skillConfig, caster, tagUseSkillAttack);
+            // case SkillEffectType.BuffEffect:
+            //     return new BuffSkillEffect(skillConfig, caster, targets);
+            // case SkillEffectType.StageEffect:
+            //     return new StageSkillEffect(skillConfig, caster, targets);
+            default:
+                UnityEngine.Debug.LogError("Unknown Skill Effect Type");
+                break;
+        }
         return null;
     }
 }
\ No newline at end of file
diff --git a/Main/System/Team/TeamBase.cs b/Main/System/Team/TeamBase.cs
index 30933ec..b0de245 100644
--- a/Main/System/Team/TeamBase.cs
+++ b/Main/System/Team/TeamBase.cs
@@ -53,8 +53,8 @@
             {
                 var fightObj = lineUp.ObjList[i];
                 TeamHero hero = new TeamHero(fightObj, this);
-                tempHeroes[fightObj.PosNum] = hero;
-                serverHeroes[fightObj.PosNum] = hero;
+                tempHeroes[hero.positionNum] = hero;
+                serverHeroes[hero.positionNum] = hero;
             }
             else
             {
diff --git a/Main/Utility/EffectPenetrationBlocker.cs b/Main/Utility/EffectPenetrationBlocker.cs
index 0c40fd2..25350a6 100644
--- a/Main/Utility/EffectPenetrationBlocker.cs
+++ b/Main/Utility/EffectPenetrationBlocker.cs
@@ -1,6 +1,10 @@
+using System;
 using System.Collections.Generic;
+using Spine.Unity;
 using UnityEngine;
 using UnityEngine.UI;
+
+
 
 /// <summary>
 /// 鐗规晥绌块�忛樆鎸″櫒
@@ -10,26 +14,28 @@
 {
     [Tooltip("鏄惁鍦║I灞傜骇涓嬭嚜鍔ㄨ皟鏁存帓搴忛『搴�")]
     public bool autoAdjustSorting = true;
-    
+
     [Tooltip("鐗规晥娓叉煋鍣紝濡傛灉涓虹┖鍒欒嚜鍔ㄨ幏鍙�")]
     public List<Renderer> effectRenderers = new List<Renderer>();
-    
+
     [Tooltip("鑷畾涔夋帓搴忛『搴忥紝浠呭湪涓嶈嚜鍔ㄨ皟鏁存椂鏈夋晥")]
     public int customSortingOrder = 0;
-    
+
     [Tooltip("鑷畾涔夋帓搴忓眰锛屼负绌哄垯浣跨敤榛樿UI灞�")]
     public string customSortingLayer = "UI";
-    
+
     [Tooltip("鐗规晥鎵�灞炵殑Canvas锛屽鏋滀负绌哄垯鏌ユ壘鐖剁骇Canvas")]
     public Canvas parentCanvas;
-    
+
     [Tooltip("鐗规晥鍦–anvas涓殑鎺掑簭鍋忕Щ閲�")]
     public int sortingOrderOffset = 1;
-    
+
     public int canvasSortingOrder = 0;
 
     public int renderQueue = 3000;//榛樿鍊�
-    
+
+    public Action<string, int> onSortingChanged;
+
     private void Awake()
     {
         transform.GetComponentsInChildren(true, effectRenderers);
@@ -56,7 +62,7 @@
             ApplySortingSettings(customSortingOrder, customSortingLayer);
         }
     }
-    
+
     private void OnEnable()
     {
         if (autoAdjustSorting)
@@ -64,14 +70,14 @@
             UpdateSortingOrder();
         }
     }
-    
+
     /// <summary>
     /// 鏇存柊鎺掑簭椤哄簭锛岀‘淇濈壒鏁堟樉绀哄湪褰撳墠UI鐣岄潰涓婃柟
     /// </summary>
     public void UpdateSortingOrder()
     {
         if (!autoAdjustSorting) return;
-        
+
         // 鑾峰彇鐖剁骇Canvas鐨勬帓搴忛『搴�
         if (parentCanvas != null)
         {
@@ -86,7 +92,7 @@
         // 灏嗙壒鏁堢殑鎺掑簭椤哄簭璁剧疆涓篊anvas鎺掑簭椤哄簭鍔犱笂鍋忕Щ閲�
         ApplySortingSettings(canvasSortingOrder + sortingOrderOffset, customSortingLayer);
     }
-    
+
     /// <summary>
     /// 搴旂敤鎺掑簭璁剧疆鍒版墍鏈夋覆鏌撳櫒鍜岀矑瀛愮郴缁�
     /// </summary>
@@ -108,8 +114,10 @@
                 }
             }
         }
+
+        onSortingChanged?.Invoke(sortingLayer, sortingOrder);
     }
-    
+
     /// <summary>
     /// 鎵嬪姩璁剧疆鎺掑簭椤哄簭
     /// </summary>
@@ -120,11 +128,11 @@
         {
             customSortingLayer = sortingLayer;
         }
-        
+
         autoAdjustSorting = false;
         ApplySortingSettings(customSortingOrder, customSortingLayer);
     }
-    
+
     /// <summary>
     /// 璁剧疆鐖剁骇Canvas
     /// </summary>
@@ -160,6 +168,7 @@
         }
     }
 
+
 #if UNITY_EDITOR
     [ContextMenu("Apply")]
     public void Apply()
diff --git a/Main/Utility/UniTaskExtension.cs b/Main/Utility/UniTaskExtension.cs
index 8ba915f..2ff6255 100644
--- a/Main/Utility/UniTaskExtension.cs
+++ b/Main/Utility/UniTaskExtension.cs
@@ -34,4 +34,25 @@
     {
         DelayFrameInternal(1, action);
     }
+
+    public static void DelayTime(this GameObject go, float time, Action action)
+    {
+        DelayTimeInternal(time, action);
+    }
+
+    public static void DelayTime(this Component cmp, float time, Action action)
+    {
+        DelayTimeInternal(time, action);
+    }
+
+    private async static UniTask DelayTimeInternal(float time, Action action)
+    {
+        if (time <= 0f)
+        {
+            action?.Invoke();
+            return;
+        }
+        await UniTask.Delay(TimeSpan.FromSeconds(time));
+        action?.Invoke();
+    }
 }
\ No newline at end of file

--
Gitblit v1.8.0