using System; using System.Collections.Generic; using System.Linq; using UnityEngine; namespace BaseGames.Animation { /// /// 动画事件配置资产(架构 §AnimationModule)。 /// 为指定 AnimationClip 声明一组事件时机,由 AnimationEventBinder 在运行时注入 Animancer 回调。 /// /// 使用方式: /// 1. 在 Inspector 中创建此资产(菜单:Animation/EventConfig)。 /// 2. 配置 TargetClip 和 Events 列表。 /// 3. 在 MonoBehaviour.Awake 中:AnimationEventBinder.Bind(clip, config, this)。 /// [CreateAssetMenu(menuName = "Animation/EventConfig")] public class AnimationEventConfigSO : ScriptableObject { [Serializable] public struct EventEntry { public AnimationEventType eventType; [Range(0f, 1f)] [Tooltip("事件在动画中的归一化时间(0 = 开始,1 = 结束)。")] public float normalizedTime; [Tooltip("附加字符串数据(可空)。用于 payload 参数。")] public string data; } [Header("绑定的动画片段")] public AnimationClip targetClip; [Header("事件时机列表(归一化时间)")] public EventEntry[] events; /// /// 用于编辑器工具验证:记录创建 Config 时 Clip 的实际帧数, /// 若 Clip 被替换(长度漂移 >5 帧)则 EventConfigEditor 显示警告。 /// [HideInInspector] public float ExpectedClipLength = -1f; // ── 运行时查询 ─────────────────────────────────────────────────── /// 按归一化时间升序返回所有事件(保证 SetCallback 顺序稳定)。 public IEnumerable SortedEvents => events != null ? events.OrderBy(e => e.normalizedTime) : Enumerable.Empty(); /// /// 返回第一个匹配类型的归一化时间;未找到时返回 -1。 /// public float GetNormalizedTime(AnimationEventType eventType) { if (events == null) return -1f; foreach (var e in events) if (e.eventType == eventType) return e.normalizedTime; return -1f; } } }