109 lines
3.9 KiB
C#
109 lines
3.9 KiB
C#
|
|
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;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|