Files
Cielonos/Assets/Scripts/SLSUtilities/FunctionalAnimation/FuncAnimPayloadBase.cs
SoulliesOfficial 39b43680a9 爆更
2026-07-18 03:16:20 -04:00

161 lines
4.8 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 Sirenix.OdinInspector;
using UnityEngine;
using UnityEngine.Serialization;
namespace SLSUtilities.FunctionalAnimation
{
[Flags]
public enum FuncAnimDisruptionCause
{
None = 0,
NaturalEnd = 1 << 0, // 动画自然播放完毕
SelfOverride = 1 << 1, // 自身通过 Play() 切入下一个动作
ExternalInterrupt = 1 << 2,// 被外部事件强制打断(如受伤、死亡、被控制)
ManualStop = 1 << 3, // 通过 Stop() 被强制停止
Any = ~0 // 任意原因
}
/// <summary>
/// (全新) 自定义Attribute用于为事件指定一个在时间轴上的颜色
/// </summary>
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
public sealed class EventColorAttribute : Attribute
{
public Color Color { get; }
public EventColorAttribute(float r, float g, float b, float a = 1.0f)
{
this.Color = new Color(r, g, b, a);
}
}
/// <summary>
/// 所有技能事件负载(Payload)的抽象基类。
/// 技能事件的具体逻辑和参数都定义在它的子类中。
/// </summary>
[Serializable]
[HideReferenceObjectPicker]
public abstract class FuncAnimPayloadBase
{
[Tooltip("是否静默执行该事件(不触发任何反馈)")]
[HorizontalGroup("Base", MarginLeft = 4, LabelWidth = 50)]
public bool mute = false;
[Tooltip("针对Loop动画只执行一次循环时不再重复触发")]
[HorizontalGroup("Base", LabelWidth = 50)]
[ShowIf("IsLooping")]
public bool isOnce = true;
protected bool IsLooping => parentData != null && parentData.animationClip != null && parentData.animationClip.isLooping;
[HorizontalGroup("Base", LabelWidth = 120)]
public bool advancedSettings = false;
[FormerlySerializedAs("eventName")]
[Tooltip("在时间轴上显示的事件名称 (如果为空,则显示类名)")]
[HideInInspector]
public string displayEventName;
[ShowIf("advancedSettings")]
public string customEventName;
public string EventName
{
get => (advancedSettings && string.IsNullOrEmpty(customEventName)) ? displayEventName : customEventName;
set
{
displayEventName = value;
customEventName = value;
}
}
[Tooltip("仅当该载荷作为打断事件Disruption / End Event时生效因为这些中断原因被打断时才触发这个事件")]
[PropertyOrder(999)]
[ShowIf("advancedSettings")]
public FuncAnimDisruptionCause validDisruptionCauses = FuncAnimDisruptionCause.Any;
[NonSerialized]
public bool hasExecuted = false;
public bool CanExecuteOnDisruption(FuncAnimDisruptionCause cause)
{
return (validDisruptionCauses & cause) != 0;
}
[NonSerialized]
public FuncAnimData parentData;
[NonSerialized]
public RuntimeFuncAnim runtimeFuncAnim;
protected IFuncAnimExecutor Executor => runtimeFuncAnim?.executor;
protected FuncAnimPayloadBase()
{
}
public virtual void Invoke()
{
}
/// <summary>
/// 创建此 Payload 的独立副本,使其拥有独立的 runtimeFuncAnim 引用。
/// 子类如果包含运行时可变的引用类型字段(如 List应 override 此方法进行深拷贝。
/// </summary>
public virtual FuncAnimPayloadBase DeepClone()
{
return (FuncAnimPayloadBase)MemberwiseClone();
}
public virtual string NameForInspector => GetType().Name;
}
[Serializable]
public abstract class FuncAnimPayloadBase<T> : FuncAnimPayloadBase
{
public T result;
protected FuncAnimPayloadBase()
{
}
public new virtual T Invoke()
{
return result;
}
}
/// <summary>
/// 一个简单的日志事件,用于调试
/// </summary>
[EventColor(1.0f, 1.0f, 0.2f)]
public class LogEvent : FuncAnimPayloadBase
{
public string message = "Hello World!";
public override void Invoke()
{
Debug.Log(message);
}
}
/// <summary>
/// 运行时动态注入的行为事件载荷。
/// </summary>
public class InvokeAction : FuncAnimPayloadBase
{
private readonly Action action;
public InvokeAction(Action action)
{
this.action = action;
}
public override void Invoke()
{
action?.Invoke();
}
}
}