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);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|