Files
Continentis/Assets/Scripts/MainGame/Commands/Cmd_PlayAnimation.cs

118 lines
4.4 KiB
C#
Raw Normal View History

2025-10-23 00:49:44 -04:00
using System;
2025-10-27 07:04:34 -04:00
using System.Collections.Generic;
using System.Linq;
2025-10-23 00:49:44 -04:00
using Continentis.MainGame.Character;
using SLSFramework.General;
using UniRx;
using UnityEngine;
2025-10-27 07:04:34 -04:00
using UnityEngine.Events;
2025-10-23 00:49:44 -04:00
namespace Continentis.MainGame.Commands
{
public class Cmd_PlayAnimation : CommandBase
{
private readonly CombatCharacterViewBase characterView;
private readonly Animator animator;
private bool waitForFinish;
private float overrideDuration;
2025-12-10 18:22:26 -05:00
private string animationName;
2025-10-23 00:49:44 -04:00
private int layer;
2025-10-27 07:04:34 -04:00
//在动画的normalizedTime执行函数
private AnimationClip clip;
private float clipScaledLength => clip.length / animator.speed;
private Dictionary<float, Action> animationActions;
2025-10-23 00:49:44 -04:00
2025-12-10 18:22:26 -05:00
public Cmd_PlayAnimation(CombatCharacterViewBase characterView, string animationName,
bool waitForFinish = true, float overrideDuration = -1, int layer = 0) : base(null)
2025-10-23 00:49:44 -04:00
{
this.characterView = characterView;
this.animator = characterView.animator;
2025-12-10 18:22:26 -05:00
this.animationName = animationName;
this.clip = null;
characterView.animations.TryGetValue(animationName, out clip);
2025-10-23 00:49:44 -04:00
this.waitForFinish = waitForFinish;
this.overrideDuration = overrideDuration;
this.layer = layer;
2025-10-27 07:04:34 -04:00
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);
2025-10-23 00:49:44 -04:00
}
protected override IObservable<Unit> OnExecute(CommandContext outerContext)
{
2025-12-10 18:22:26 -05:00
if (animator == null || clip == null || string.IsNullOrEmpty(animationName))
2025-10-23 00:49:44 -04:00
{
Debug.LogWarning("Animator or stateName is null or empty.");
return Observable.Return(Unit.Default);
}
2025-12-10 18:22:26 -05:00
string finalAnimationName = animationName;
if (!characterView.animations.ContainsKey(animationName))
2025-10-23 00:49:44 -04:00
{
2025-12-10 18:22:26 -05:00
finalAnimationName = "Action";
2025-10-23 00:49:44 -04:00
}
2025-12-10 18:22:26 -05:00
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);
}
2025-10-27 07:04:34 -04:00
//监听动画进度以执行函数独立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); //确保只执行一次
}
}
});
}
2025-10-23 00:49:44 -04:00
if (waitForFinish)
{
2025-12-10 18:22:26 -05:00
float animationDuration = overrideDuration >= 0 ? overrideDuration / animator.speed : clipScaledLength;
2025-10-23 00:49:44 -04:00
return Observable.Timer(TimeSpan.FromSeconds(animationDuration)).AsUnitObservable();
}
else
{
return Observable.Return(Unit.Default);
}
}
}
}