Files
Continentis/Assets/Scripts/MainGame/Commands/Cmd_PlayAnimation.cs
2025-12-10 18:22:26 -05:00

118 lines
4.4 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections.Generic;
using System.Linq;
using Continentis.MainGame.Character;
using SLSFramework.General;
using UniRx;
using UnityEngine;
using UnityEngine.Events;
namespace Continentis.MainGame.Commands
{
public class Cmd_PlayAnimation : CommandBase
{
private readonly CombatCharacterViewBase characterView;
private readonly Animator animator;
private bool waitForFinish;
private float overrideDuration;
private string animationName;
private int layer;
//在动画的normalizedTime执行函数
private AnimationClip clip;
private float clipScaledLength => clip.length / animator.speed;
private Dictionary<float, Action> animationActions;
public Cmd_PlayAnimation(CombatCharacterViewBase characterView, string animationName,
bool waitForFinish = true, float overrideDuration = -1, int layer = 0) : base(null)
{
this.characterView = characterView;
this.animator = characterView.animator;
this.animationName = animationName;
this.clip = null;
characterView.animations.TryGetValue(animationName, out clip);
this.waitForFinish = waitForFinish;
this.overrideDuration = overrideDuration;
this.layer = layer;
this.animationActions = new Dictionary<float, Action>();
}
public Cmd_PlayAnimation AddAction(float normalizedDuration, Action action)
{
animationActions[normalizedDuration] = action;
return this;
}
public Cmd_PlayAnimation AddAction(int frame, Action action)
{
float normalizedDuration = frame / (clip.frameRate * clip.length);
return AddAction(normalizedDuration, action);
}
public Cmd_PlayAnimation AddAction<T>(float normalizedDuration, string selfContextKey, Action<T> action)
{
T param = selfContext.GetInfo<T>(selfContextKey);
animationActions[normalizedDuration] = () => action(param);
return this;
}
public Cmd_PlayAnimation AddAction<T>(int frame, string selfContextKey, Action<T> action)
{
float normalizedDuration = frame / (clip.frameRate * clip.length);
return AddAction(normalizedDuration, selfContextKey, action);
}
protected override IObservable<Unit> OnExecute(CommandContext outerContext)
{
if (animator == null || clip == null || string.IsNullOrEmpty(animationName))
{
Debug.LogWarning("Animator or stateName is null or empty.");
return Observable.Return(Unit.Default);
}
string finalAnimationName = animationName;
if (!characterView.animations.ContainsKey(animationName))
{
finalAnimationName = "Action";
}
if (characterView.animations.TryGetValue(finalAnimationName, out clip))
{
characterView.animatorPlus2D.Play(clip);
}
else
{
Debug.LogWarning($"Animation clip not found for state: {finalAnimationName}");
return Observable.Return(Unit.Default);
}
//监听动画进度以执行函数独立Observable
if (animationActions.Count > 0)
{
Observable.EveryUpdate().TakeUntil(Observable.Timer(TimeSpan.FromSeconds(clipScaledLength))).Subscribe(_ =>
{
float normalizedTime = animator.GetCurrentAnimatorStateInfo(layer).normalizedTime % 1f;
foreach (var kvp in animationActions.ToList())
{
if (normalizedTime >= kvp.Key)
{
kvp.Value?.Invoke();
animationActions.Remove(kvp.Key); //确保只执行一次
}
}
});
}
if (waitForFinish)
{
float animationDuration = overrideDuration >= 0 ? overrideDuration / animator.speed : clipScaledLength;
return Observable.Timer(TimeSpan.FromSeconds(animationDuration)).AsUnitObservable();
}
else
{
return Observable.Return(Unit.Default);
}
}
}
}