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

115 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;
private string stateName;
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
public Cmd_PlayAnimation(CombatCharacterViewBase characterView, string stateName,
bool waitForFinish = false, float overrideDuration = -1, int layer = 0) : base(null)
{
this.characterView = characterView;
this.animator = characterView.animator;
this.stateName = stateName;
2025-10-27 07:04:34 -04:00
this.clip = characterView.animationClips[stateName];
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)
{
if (animator == null)
{
Debug.LogWarning("Animator or stateName is null or empty.");
return Observable.Return(Unit.Default);
}
if (!animator.HasState(layer, Animator.StringToHash(stateName)))
{
if (!animator.HasState(layer, Animator.StringToHash("Default")))
{
Debug.LogWarning($"Animator does not have state: {stateName}, and Default state is also missing.");
return Observable.Return(Unit.Default);
}
stateName = "Default"; // Fallback to Default state
Debug.Log($"Animator does not have state: {stateName}. Falling back to Default state.");
}
animator.CrossFade(stateName, 0f, layer, 0f);
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)
{
float animationDuration = overrideDuration >= 0 ? overrideDuration : characterView.animationClips[stateName].length;
return Observable.Timer(TimeSpan.FromSeconds(animationDuration)).AsUnitObservable();
}
else
{
return Observable.Return(Unit.Default);
}
}
}
}