161 lines
4.8 KiB
C#
161 lines
4.8 KiB
C#
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();
|
||
}
|
||
}
|
||
} |