Files
Continentis/Assets/Scripts/MainGame/Character/CharacterView/FrameAnimator.cs

109 lines
3.9 KiB
C#
Raw Normal View History

2026-04-01 12:23:27 -04:00
using System;
using System.Collections;
using System.Collections.Generic;
using AnimatorPlus;
using SLSFramework.General;
using UnityEngine;
namespace Continentis.MainGame.Character
{
/// <summary>
/// Tier 2 动画驱动器:帧动画方案,基于 AnimatorPlus2D + AnimationClip。
/// 通过 CharacterData.animations 映射表驱动 Sprite Sheet 帧动画。
/// 适合有完整帧动画序列的像素风角色(如 PixelFantasy 系列)。
/// </summary>
public class FrameAnimator : MonoBehaviour, ICharacterAnimator
{
private AnimatorPlus2D _animatorPlus;
private SerializableDictionary<string, AnimationClip> _animations;
private Coroutine _completionCoroutine;
// ── ICharacterAnimator ──────────────────────────────────────────────
/// <summary>
/// 初始化:从 CombatCharacterViewBase 获取 AnimatorPlus2D 引用和动画映射表。
/// </summary>
public void InitializeAnimator(CombatCharacterViewBase view)
{
_animatorPlus = view.animatorPlus2D;
// 从 CharacterData 拷贝动画映射
_animations = new SerializableDictionary<string, AnimationClip>();
foreach (KeyValuePair<string, AnimationClip> 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 动画,无法初始化。");
}
}
/// <summary>
/// 播放指定动作的 AnimationClip播完自动回 Idle 并触发回调。
/// </summary>
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));
}
}
/// <summary>
/// 立即停止当前动作,切回 Idle。
/// </summary>
public void ReturnToIdle()
{
StopCompletionCoroutine();
_animatorPlus.Stop();
}
/// <summary>
/// 暂停或恢复 PlayableGraph。
/// </summary>
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;
}
}
}
}