| | |
| | | return true; |
| | | } |
| | | |
| | | public Spine.TrackEntry PlaySkillAnimation(SkillConfig skillConfig, SkillBase skillBase, bool isSubSkill, Action onComplete = null) |
| | | public Spine.TrackEntry PlaySkillAnimation(SkillConfig skillConfig, SkillSkinConfig skillSkinConfig, SkillBase skillBase, bool isSubSkill, Action onComplete = null) |
| | | { |
| | | if (skillConfig == null) |
| | | { |
| | |
| | | } |
| | | |
| | | // 如果没有动画名称,使用无动画模式 |
| | | if (string.IsNullOrEmpty(skillConfig.SkillMotionName)) |
| | | if (string.IsNullOrEmpty(skillSkinConfig.SkillMotionName)) |
| | | { |
| | | PlaySkillNoAnim(skillConfig, skillBase, onComplete, isSubSkill); |
| | | PlaySkillNoAnim(skillConfig, skillSkinConfig, skillBase, onComplete, isSubSkill); |
| | | return null; |
| | | } |
| | | |
| | | Spine.Animation targetAnim = FindAnim(skillConfig.SkillMotionName); |
| | | Spine.Animation targetAnim = FindAnim(skillSkinConfig.SkillMotionName); |
| | | if (targetAnim == null) |
| | | { |
| | | skillBase.ForceFinished(); |
| | | return null; |
| | | } |
| | | |
| | | return ExecuteSkillAnim(skillConfig, skillBase, onComplete, targetAnim, true, isSubSkill); |
| | | return ExecuteSkillAnim(skillConfig, skillSkinConfig, skillBase, onComplete, targetAnim, true, isSubSkill); |
| | | } |
| | | |
| | | |
| | | private Spine.TrackEntry ExecuteSkillAnim(SkillConfig skillConfig, SkillBase skillBase, Action onComplete, |
| | | private Spine.TrackEntry ExecuteSkillAnim(SkillConfig skillConfig, SkillSkinConfig skillSkinConfig, SkillBase skillBase, Action onComplete, |
| | | Spine.Animation targetAnim, bool hasAnim, bool isSubSkill) |
| | | { |
| | | |
| | | int loopCount = skillConfig.LoopCount; |
| | | int loopCount = skillSkinConfig.LoopCount; |
| | | // 前摇 |
| | | int startupFrames = skillConfig.StartupFrames; |
| | | int startupFrames = skillSkinConfig.StartupFrames; |
| | | // 中摇 |
| | | int[] activeFrames = skillConfig.ActiveFrames ?? new int[0]; |
| | | int[] activeFrames = skillSkinConfig.ActiveFrames ?? new int[0]; |
| | | int frameCount = activeFrames.Length; |
| | | // 后摇 |
| | | float recoveryFrame = skillConfig.RecoveryFrames; |
| | | float recoveryFrame = skillSkinConfig.RecoveryFrames; |
| | | |
| | | // 如果前中后摇没有配置 那么默认给一个1 2 3的帧数 |
| | | if (startupFrames <= 0 && frameCount == 0 && recoveryFrame <= 0f) |
| | |
| | | { |
| | | // 轨道池耗尽或未初始化,回退到无动画模式 |
| | | Debug.LogWarning($"子技能轨道池已满或未初始化,技能{skillConfig.SkillID}使用无动画模式"); |
| | | PlaySkillNoAnim(skillConfig, skillBase, onComplete, isSubSkill); |
| | | PlaySkillNoAnim(skillConfig, skillSkinConfig, skillBase, onComplete, isSubSkill); |
| | | return null; |
| | | } |
| | | } |
| | |
| | | { |
| | | if (skillBase != null && !skillBase.IsFinished()) |
| | | { |
| | | PlaySkillAnimation(skillConfig, skillBase, isSubSkill, onComplete); |
| | | PlaySkillAnimation(skillConfig, skillSkinConfig, skillBase, isSubSkill, onComplete); |
| | | } |
| | | }); |
| | | return null; |
| | |
| | | } |
| | | |
| | | // 各阶段回调(原有逻辑) |
| | | if (!beginTriggered && currentFrame >= skillConfig.StartupFrames && currentLoop == 0) |
| | | if (!beginTriggered && currentFrame >= skillSkinConfig.StartupFrames && currentLoop == 0) |
| | | { |
| | | beginTriggered = true; |
| | | skillBase.OnStartSkillFrameEnd(); |
| | | } |
| | | |
| | | if (!middleStarted && currentFrame >= skillConfig.StartupFrames && currentLoop <= loopCount) |
| | | if (!middleStarted && currentFrame >= skillSkinConfig.StartupFrames && currentLoop <= loopCount) |
| | | { |
| | | middleStarted = true; |
| | | skillBase.OnMiddleFrameStart(currentLoop); |
| | |
| | | { |
| | | if (hasAnim) |
| | | { |
| | | skillTrack.TrackTime = skillConfig.StartupFrames / BattleConst.skillMotionFps; |
| | | skillTrack.TrackTime = skillSkinConfig.StartupFrames / BattleConst.skillMotionFps; |
| | | } |
| | | else |
| | | { |
| | | // 为下一 loop 重置 startTime,并且更新 pausedAccumulatedAtStart(以保持基线) |
| | | startTime = Time.time - (skillConfig.StartupFrames / BattleConst.skillMotionFps); |
| | | startTime = Time.time - (skillSkinConfig.StartupFrames / BattleConst.skillMotionFps); |
| | | pausedAccumulatedAtStart = pausedAccumulated; |
| | | } |
| | | } |
| | |
| | | return targetAnim; |
| | | } |
| | | |
| | | private void PlaySkillNoAnim(SkillConfig skillConfig, SkillBase skillBase, Action onComplete, bool isSubSkill) => |
| | | ExecuteSkillAnim(skillConfig, skillBase, onComplete, null, false, isSubSkill); |
| | | private void PlaySkillNoAnim(SkillConfig skillConfig, SkillSkinConfig skillSkinConfig, SkillBase skillBase, Action onComplete, bool isSubSkill) => |
| | | ExecuteSkillAnim(skillConfig, skillSkinConfig, skillBase, onComplete, null, false, isSubSkill); |
| | | |
| | | protected virtual void SetupAnimationHandlers() |
| | | { |
| | |
| | | } |
| | | } |
| | | |
| | | public bool CanCastSkill(SkillConfig skillConfig) |
| | | public bool CanCastSkill(SkillSkinConfig skillSkinConfig) |
| | | { |
| | | return !playingSkillWithAnim || string.IsNullOrEmpty(skillConfig.SkillMotionName); |
| | | return !playingSkillWithAnim || string.IsNullOrEmpty(skillSkinConfig.SkillMotionName); |
| | | } |
| | | |
| | | public bool CanStartDeath() |