yyl
2026-04-03 99a11d2bb19d74f6cc8584ac16838062af4fb301
Main/System/Battle/Skill/SkillBase.cs
@@ -195,7 +195,7 @@
        
    }
    // 技能运行主逻辑:处理技能效果和其他技能动作
    // 技能运行主逻辑:仅驱动技能效果(skillEffect),子技能和死亡由IsFinished()推进
    public virtual void Run()
    {
        if (skillEffect != null)
@@ -211,8 +211,6 @@
            }
            return;
        }
    }
    protected void ShadowIllutionCreate(bool create)
@@ -370,7 +368,7 @@
            return;
        }
        int mainTargetPosNum = BattleUtility.GetMainTargetPositionNum(this, caster, tagUseSkillAttack.HurtList.ToList(), skillConfig);
        int mainTargetPosNum = BattleUtility.GetMainTargetPositionNum(this, caster, tagUseSkillAttack.HurtList, skillConfig);
        BattleCamp battleCamp = skillConfig.TagFriendly != 0 ? caster.Camp : caster.GetEnemyCamp();
        RectTransform targetTrans = battleField.GetTeamNode(battleCamp, mainTargetPosNum);
@@ -482,9 +480,9 @@
    protected virtual void OnAllAttackMoveFinished()
    {
        moveFinished = true;
        List<BattleObject> allList = battleField.battleObjMgr.allBattleObjDict.Values.ToList<BattleObject>();
        foreach (BattleObject bo in allList)
        foreach (var kv in battleField.battleObjMgr.allBattleObjDict)
        {
            BattleObject bo = kv.Value;
            bo.layerMgr.SetFront();
            bo.GetHeroInfoBar()?.SetActive(true);
        }
@@ -672,7 +670,7 @@
        // 确保施法者也被高亮(原逻辑)
        var highlightList = new List<BattleObject>(targetSet) { caster };
        var allList = battleField.battleObjMgr.allBattleObjDict.Values.ToList();
        var allList = battleField.battleObjMgr.allBattleObjDict.Values;
        // 构造集合便于判断
        var targetSetLookup = new HashSet<BattleObject>(targetSet);
@@ -1022,7 +1020,12 @@
        // 获取并分配掉落物品和经验
        var dropPack = PackManager.Instance.GetSinglePack(PackType.DropItem);
        var itemDict = dropPack.GetAllItems();
        List<ItemModel> itemList = new List<ItemModel>(itemDict.Values.Where(item => item != null && item.isAuction));
        List<ItemModel> itemList = new List<ItemModel>();
        foreach (var item in itemDict.Values)
        {
            if (item != null && item.isAuction)
                itemList.Add(item);
        }
        var dropAssign = AssignDrops(itemList, deadPackList.Count);
        var expAssign = AssignExp(expPackList, deadPackList.Count);
@@ -1041,7 +1044,9 @@
                continue;
            }
            
            List<int> itemIndexList = dropAssign[i].Select(item => item.gridIndex).ToList();
            List<int> itemIndexList = new List<int>(dropAssign[i].Count);
            for (int j = 0; j < dropAssign[i].Count; j++)
                itemIndexList.Add(dropAssign[i][j].gridIndex);
            
            BattleDrops battleDrops = new BattleDrops()
            {
@@ -1238,7 +1243,8 @@
        return false;
    }
    // 检查技能是否完成:综合检查所有完成条件
    // 检查技能是否完成:同时推进状态(清理完成的子技能、处理剩余包、触发死亡判定)
    // 注意:此方法有副作用,这是设计使然——由SkillRecordAction.Run()每帧调用来驱动状态推进
    public virtual bool IsFinished()
    {
        if (!isPlay) return false;
@@ -1254,7 +1260,7 @@
            tempRetValue = false;
        }
        // 检查其他技能动作是否完成
        // 检查跟进的技能动作是否完成(追击/连击/反击等)
        if (currentWaitingSkill.Count > 0)
        {
            if (currentWaitingSkill.Any(s => s.IsFinished()))
@@ -1273,7 +1279,6 @@
            return false;
        }
        // 检查最终完成状态
        if (isFinished && moveFinished)
        {
@@ -1283,7 +1288,7 @@
                return false;
            }
            //  如果自己内部的recora action的 inner record player还有没执行完的包 也是返回false
            //  如果自己内部的 innerRecordPlayer 还有没执行完的包 也是返回false
            if (ownRecordAction != null && ownRecordAction.GetInnerRecordPlayer().IsPlaying())
            {
                return false;
@@ -1294,7 +1299,6 @@
            {
                battleField.RemoveCastingSkill(caster.ObjID, this);
                
                //  传递parentRecordAction,让死亡技能等待当前技能完成
                DeathRecordAction recordAction = battleField.OnObjsDead(new List<BattleDeadPack>(tempDeadPackList.Values), null, ownRecordAction);
                if (null != recordAction)
                {
@@ -1362,6 +1366,12 @@
            // 取消幻影效果
            caster.ShowIllusionShadow(false);
            // 重置MotionBase的技能动画状态,防止playingSkillWithAnim卡住后续技能
            if (caster is HeroBattleObject heroCaster)
            {
                heroCaster.ForceResetMotionSkillState();
            }
        }
        // 5. 恢复 UI 状态
@@ -1490,14 +1500,22 @@
                skillRecordAction.fromSkill = this;
                currentWaitingSkill.Add(skillRecordAction);
                //  需要给真正parent播的
                //  根据后续技能的属性决定是否需要等待当前技能归位
                RecordAction waitAction = GetFollowUpWaitAction(skillRecordAction);
                if (skillRecordAction.useParentRecordPlayer && skillRecordAction.parentSkillAction != null)
                {
                    skillRecordAction.parentSkillAction.GetInnerRecordPlayer().PlayRecord(skillRecordAction);
                    if (waitAction != null)
                        skillRecordAction.parentSkillAction.GetInnerRecordPlayer().PlayRecord(skillRecordAction, waitAction);
                    else
                        skillRecordAction.parentSkillAction.GetInnerRecordPlayer().PlayRecord(skillRecordAction);
                }
                else
                {
                    ownRecordAction.GetInnerRecordPlayer().PlayRecord(skillRecordAction);
                    if (waitAction != null)
                        ownRecordAction.GetInnerRecordPlayer().PlayRecord(skillRecordAction, waitAction);
                    else
                        ownRecordAction.GetInnerRecordPlayer().PlayRecord(skillRecordAction);
                }
                return false;
@@ -1539,6 +1557,40 @@
        return true;
    }
    /// <summary>
    /// 判定后续技能(追击/连击/反击等)是否需要等待当前技能完成动作后再释放
    /// 综合判别:技能是否有动画、释放模式是否需要位移、是否同一施法者
    /// 仅在确认安全时返回waitAction,避免不必要的等待和潜在的跨角色相互等待
    /// </summary>
    private RecordAction GetFollowUpWaitAction(SkillRecordAction followUp)
    {
        // 当前技能已经归位,无需等待
        if (moveFinished) return null;
        if (followUp.skillBase == null) return null;
        // 后续技能没有动画动作(无SkillMotionName),不涉及位移,无需等待归位
        // 这类技能在CanCastSkill中也不受playingSkillWithAnim限制
        var followUpSkin = followUp.skillBase.skillSkinConfig;
        if (followUpSkin == null || string.IsNullOrEmpty(followUpSkin.SkillMotionName))
            return null;
        // 后续技能原地释放(None/Self),虽有动画但不需要位移到目标,无需等待
        if (followUpSkin.castMode == SkillCastMode.None || followUpSkin.castMode == SkillCastMode.Self)
            return null;
        // 同一施法者的后续技能(连击等):必须等待归位
        // 原因:同一角色的CastToEnemy/CastToTarget会MoveToTarget,
        // 如果上一个技能的DOTween归位还没完成就发起新位移,两个DOTween会冲突
        if (followUp.skillBase.caster == caster)
            return ownRecordAction;
        // 不同施法者的后续技能(追击/反击等):不添加等待
        // 原因:不同角色从各自位置出发,不存在DOTween冲突
        // 注意:此处不添加跨角色等待关系,避免技能链A等B、B等A的相互等待风险
        return null;
    }
    // 添加清理方法:防止内存泄漏
    public virtual void Cleanup()
    {