| | |
| | | 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 SkeletonIllusionShadow illusionShadow; |
| | | private bool playingSkillAnim = false; |
| | | |
| | |
| | | public virtual void Release() |
| | | { |
| | | trackEntryCallbacks.Clear(); |
| | | activeSkillTracks.Clear(); |
| | | if (animState != null) |
| | | { |
| | | animState.Complete -= OnAnimationComplete; |
| | |
| | | return null; |
| | | } |
| | | |
| | | if (string.IsNullOrEmpty(skillConfig.SkillMotionName)) |
| | | // 子技能强制使用无动画模式,或者如果没有动画名称 |
| | | if (isSubSkill || string.IsNullOrEmpty(skillConfig.SkillMotionName)) |
| | | { |
| | | PlaySkillNoAnim(skillConfig, skillBase, onComplete, isSubSkill); |
| | | return null; |
| | |
| | | int frameCount = activeFrames.Length; |
| | | float recoveryFrame = skillConfig.RecoveryFrames; |
| | | |
| | | // 主技能用 track 0,子技能用 track 1 |
| | | int trackIndex = isSubSkill ? 1 : 0; |
| | | Spine.TrackEntry skillTrack = null; |
| | | |
| | | if (hasAnim) |
| | | { |
| | | skillTrack = animState.SetAnimation(0, targetAnim, false); |
| | | skillTrack = animState.SetAnimation(trackIndex, targetAnim, false); |
| | | if (null == skillTrack || skillConfig.SkillID == 3008020) |
| | | { |
| | | Debug.Break(); |
| | | } |
| | | |
| | | // 只有主技能才更新 currentTrack |
| | | if (!isSubSkill) |
| | | currentTrack = skillTrack; |
| | | |
| | | activeSkillTracks[trackIndex] = skillTrack; |
| | | } |
| | | |
| | | playingSkillAnim = true; |
| | |
| | | // 新增:记录技能开始时的 pausedAccumulated 基线,用于后续计算该技能自身的暂停时长 |
| | | float pausedAccumulatedAtStart = pausedAccumulated; |
| | | |
| | | // startTime 表示技能“本地逻辑时间”的起点(以 Time.time 为基准) |
| | | // startTime 表示技能"本地逻辑时间"的起点(以 Time.time 为基准) |
| | | float startTime = hasAnim ? 0f : Time.time; |
| | | |
| | | skillBase.OnSkillStart(); |
| | |
| | | if (skillBase.IsFinished()) |
| | | { |
| | | // 清理并退出(保证状态一致) |
| | | if (skillTrack != null && activeSkillTracks.ContainsKey(trackIndex)) |
| | | { |
| | | if (activeSkillTracks[trackIndex] == skillTrack) |
| | | activeSkillTracks.Remove(trackIndex); |
| | | } |
| | | |
| | | // 只有当没有其他活跃技能时才复位 playingSkillAnim |
| | | if (activeSkillTracks.Count == 0) |
| | | playingSkillAnim = false; |
| | | |
| | | RemoveAction(frameHandler); |
| | | return; |
| | | } |
| | |
| | | } |
| | | else |
| | | { |
| | | // 使用 pausedAccumulatedAtStart 来计算“这个技能自开始以来的暂停总时长” |
| | | // 使用 pausedAccumulatedAtStart 来计算"这个技能自开始以来的暂停总时长" |
| | | float adjustedTime = Time.time; |
| | | float thisSkillPaused = pausedAccumulated - pausedAccumulatedAtStart; |
| | | if (thisSkillPaused < 0f) thisSkillPaused = 0f; // 保险防护 |
| | |
| | | |
| | | if (hasAnim) |
| | | { |
| | | if (currentTrack != skillTrack) |
| | | // 检查当前轨道是否被新技能覆盖 |
| | | if (!activeSkillTracks.ContainsKey(trackIndex) || activeSkillTracks[trackIndex] != skillTrack) |
| | | { |
| | | Debug.LogError("技能动画被打断,强制结束 " + skillConfig.SkillID); |
| | | skillBase.ForceFinished(); |
| | | |
| | | // 清理并确保状态复位 |
| | | RemoveAction(frameHandler); |
| | | if (activeSkillTracks.Count == 0) |
| | | playingSkillAnim = false; |
| | | return; |
| | | } |
| | |
| | | Debug.LogError("技能动画播放失败,强制结束 " + skillConfig.SkillID); |
| | | skillBase.ForceFinished(); |
| | | RemoveAction(frameHandler); |
| | | if (activeSkillTracks.ContainsKey(trackIndex)) |
| | | activeSkillTracks.Remove(trackIndex); |
| | | if (activeSkillTracks.Count == 0) |
| | | playingSkillAnim = false; |
| | | return; |
| | | } |
| | |
| | | { |
| | | finalEnded = true; |
| | | |
| | | // 一定要把 playingSkillAnim 复位(无论是否是子技能),否则可能导致后续动画被拦截 |
| | | // 清理技能轨道 |
| | | if (skillTrack != null && activeSkillTracks.ContainsKey(trackIndex)) |
| | | { |
| | | if (activeSkillTracks[trackIndex] == skillTrack) |
| | | activeSkillTracks.Remove(trackIndex); |
| | | } |
| | | |
| | | // 只有当没有其他活跃技能时才复位 playingSkillAnim |
| | | if (activeSkillTracks.Count == 0) |
| | | playingSkillAnim = false; |
| | | |
| | | RemoveAction(frameHandler); |
| | |
| | | { |
| | | trackEntryCallbacks.Clear(); |
| | | runningActions.Clear(); |
| | | activeSkillTracks.Clear(); |
| | | playingSkillAnim = false; |
| | | PlayAnimation(MotionName.idle, true); |
| | | } |