yyl
4 天以前 ca85c0a70922aa219f6cad5e8af8ad004c3cb4b3
Main/System/Battle/Motion/MotionBase.cs
@@ -23,7 +23,12 @@
    protected Spine.Skeleton skeleton;
    protected float defaultMixDuration = 0f;
    private Spine.TrackEntry currentTrack;
    private Dictionary<int, Spine.TrackEntry> activeSkillTracks = new Dictionary<int, Spine.TrackEntry>(); // 改为字典:trackIndex -> TrackEntry
    private Dictionary<int, Spine.TrackEntry> activeSkillTracks = new Dictionary<int, Spine.TrackEntry>();
    // 子技能轨道池管理(在Init中初始化,不要在这里初始化)
    private Queue<int> availableSubTracks;
    private Dictionary<SkillBase, int> subSkillTrackMap = new Dictionary<SkillBase, int>();
    private SkeletonIllusionShadow illusionShadow;
    private bool playingSkillAnim = false;
@@ -52,6 +57,11 @@
        if (animState != null)
            animState.Data.DefaultMix = defaultMixDuration;
        // 初始化子技能轨道池
        availableSubTracks = new Queue<int>();
        for (int i = 1; i <= 8; i++)
            availableSubTracks.Enqueue(i);
        PlayAnimation(MotionName.idle, true);
        SetupAnimationHandlers();
        
@@ -63,6 +73,8 @@
    {
        trackEntryCallbacks.Clear();
        activeSkillTracks.Clear();
        availableSubTracks?.Clear();
        subSkillTrackMap.Clear();
        if (animState != null)
        {
            animState.Complete -= OnAnimationComplete;
@@ -109,8 +121,8 @@
            return null;
        }
        // 子技能强制使用无动画模式,或者如果没有动画名称
        if (isSubSkill || string.IsNullOrEmpty(skillConfig.SkillMotionName))
        // 如果没有动画名称,使用无动画模式
        if (string.IsNullOrEmpty(skillConfig.SkillMotionName))
        {
            PlaySkillNoAnim(skillConfig, skillBase, onComplete, isSubSkill);
            return null;
@@ -136,13 +148,41 @@
        int frameCount = activeFrames.Length;
        float recoveryFrame = skillConfig.RecoveryFrames;
        // 主技能用 track 0,子技能用 track 1
        int trackIndex = isSubSkill ? 1 : 0;
        // 轨道分配策略:主技能用 track 0,子技能从轨道池分配
        int trackIndex = 0;
        if (isSubSkill)
        {
            if (availableSubTracks != null && availableSubTracks.Count > 0)
            {
                trackIndex = availableSubTracks.Dequeue();
                subSkillTrackMap[skillBase] = trackIndex;
            }
            else
            {
                // 轨道池耗尽或未初始化,回退到无动画模式
                Debug.LogWarning($"子技能轨道池已满或未初始化,技能{skillConfig.SkillID}使用无动画模式");
                PlaySkillNoAnim(skillConfig, skillBase, onComplete, isSubSkill);
                return null;
            }
        }
        Spine.TrackEntry skillTrack = null;
        
        if (hasAnim)
        {
            skillTrack = animState.SetAnimation(trackIndex, targetAnim, false);
            if (null == skillTrack)
            {
                Debug.LogError($"技能 {skillConfig.SkillID} 动画设置失败");
                // 如果是子技能且分配了轨道,需要回收
                if (isSubSkill && subSkillTrackMap.ContainsKey(skillBase))
                {
                    if (availableSubTracks != null)
                        availableSubTracks.Enqueue(subSkillTrackMap[skillBase]);
                    subSkillTrackMap.Remove(skillBase);
                }
                return null;
            }
            
            // 只有主技能才更新 currentTrack
            if (!isSubSkill)
@@ -175,6 +215,14 @@
                {
                    if (activeSkillTracks[trackIndex] == skillTrack)
                        activeSkillTracks.Remove(trackIndex);
                }
                // 回收子技能轨道
                if (isSubSkill && subSkillTrackMap.ContainsKey(skillBase))
                {
                    if (availableSubTracks != null)
                        availableSubTracks.Enqueue(subSkillTrackMap[skillBase]);
                    subSkillTrackMap.Remove(skillBase);
                }
                
                // 只有当没有其他活跃技能时才复位 playingSkillAnim
@@ -214,6 +262,15 @@
                    // 清理并确保状态复位
                    RemoveAction(frameHandler);
                    // 回收子技能轨道
                    if (isSubSkill && subSkillTrackMap.ContainsKey(skillBase))
                    {
                        if (availableSubTracks != null)
                            availableSubTracks.Enqueue(subSkillTrackMap[skillBase]);
                        subSkillTrackMap.Remove(skillBase);
                    }
                    if (activeSkillTracks.Count == 0)
                        playingSkillAnim = false;
                    return;
@@ -227,6 +284,15 @@
                    RemoveAction(frameHandler);
                    if (activeSkillTracks.ContainsKey(trackIndex))
                        activeSkillTracks.Remove(trackIndex);
                    // 回收子技能轨道
                    if (isSubSkill && subSkillTrackMap.ContainsKey(skillBase))
                    {
                        if (availableSubTracks != null)
                            availableSubTracks.Enqueue(subSkillTrackMap[skillBase]);
                        subSkillTrackMap.Remove(skillBase);
                    }
                    if (activeSkillTracks.Count == 0)
                        playingSkillAnim = false;
                    return;
@@ -303,6 +369,14 @@
                    {
                        if (activeSkillTracks[trackIndex] == skillTrack)
                            activeSkillTracks.Remove(trackIndex);
                    }
                    // 回收子技能轨道
                    if (isSubSkill && subSkillTrackMap.ContainsKey(skillBase))
                    {
                        if (availableSubTracks != null)
                            availableSubTracks.Enqueue(subSkillTrackMap[skillBase]);
                        subSkillTrackMap.Remove(skillBase);
                    }
                    // 只有当没有其他活跃技能时才复位 playingSkillAnim
@@ -436,6 +510,17 @@
        trackEntryCallbacks.Clear();
        runningActions.Clear();
        activeSkillTracks.Clear();
        // 重置子技能轨道池
        if (availableSubTracks == null)
            availableSubTracks = new Queue<int>();
        else
            availableSubTracks.Clear();
        subSkillTrackMap.Clear();
        for (int i = 1; i <= 8; i++)
            availableSubTracks.Enqueue(i);
        playingSkillAnim = false;
        PlayAnimation(MotionName.idle, true);
    }