using System; using System.Collections; using System.Collections.Generic; using AnimatorPlus; using SLSFramework.General; using UnityEngine; namespace Continentis.MainGame.Character { /// /// Tier 2 动画驱动器:帧动画方案,基于 AnimatorPlus2D + AnimationClip。 /// 通过 CharacterData.animations 映射表驱动 Sprite Sheet 帧动画。 /// 适合有完整帧动画序列的像素风角色(如 PixelFantasy 系列)。 /// public class FrameAnimator : MonoBehaviour, ICharacterAnimator { private AnimatorPlus2D _animatorPlus; private SerializableDictionary _animations; private Coroutine _completionCoroutine; // ── ICharacterAnimator ────────────────────────────────────────────── /// /// 初始化:从 CombatCharacterViewBase 获取 AnimatorPlus2D 引用和动画映射表。 /// public void InitializeAnimator(CombatCharacterViewBase view) { _animatorPlus = view.animatorPlus2D; // 从 CharacterData 拷贝动画映射 _animations = new SerializableDictionary(); foreach (KeyValuePair pair in view.character.data.animations) { _animations.Add(pair.Key, pair.Value); } // 设置 Idle 并初始化 Playable Graph if (_animations.TryGetValue("Idle", out AnimationClip idle)) { _animatorPlus.defaultIdleClip = idle; _animatorPlus.Initialize(); } else { Debug.LogError($"[FrameAnimator] 角色 '{view.character.data.displayName}' 缺少 Idle 动画,无法初始化。"); } } /// /// 播放指定动作的 AnimationClip,播完自动回 Idle 并触发回调。 /// public void PlayAction(string actionName, float speed = 1f, Action onComplete = null) { StopCompletionCoroutine(); if (!_animations.TryGetValue(actionName, out AnimationClip clip)) { Debug.LogWarning($"[FrameAnimator] 找不到动画 '{actionName}',跳过播放。"); onComplete?.Invoke(); return; } _animatorPlus.Play(clip, speed); // 动画播完后触发回调(AnimatorPlus2D 自动回 Idle,此处仅等待时长) if (onComplete != null) { float duration = clip.length / Mathf.Max(speed, 0.01f); _completionCoroutine = StartCoroutine(WaitForCompletion(duration, onComplete)); } } /// /// 立即停止当前动作,切回 Idle。 /// public void ReturnToIdle() { StopCompletionCoroutine(); _animatorPlus.Stop(); } /// /// 暂停或恢复 PlayableGraph。 /// public void SetPause(bool isPaused) { _animatorPlus.SetPause(isPaused); } // ── 内部逻辑 ──────────────────────────────────────────────────────── private IEnumerator WaitForCompletion(float duration, Action onComplete) { yield return new WaitForSeconds(duration); onComplete?.Invoke(); _completionCoroutine = null; } private void StopCompletionCoroutine() { if (_completionCoroutine != null) { StopCoroutine(_completionCoroutine); _completionCoroutine = null; } } } }