unity动画序列帧代码实现 代码缓存_第一章.md 33 KB

单序列帧动画 & Example示例

SequenceFramePlayer

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

/// <summary>
/// 动画序列数据结构
/// </summary>
[System.Serializable]
public class AnimationSequence
{
    [Header("序列设置")]
    public string name = "Animation"; // 动画名称
    public Sprite[] frames; // 序列帧图片数组
    [Range(1f, 120f)]
    public float framerate = 30f; // 播放帧率
    public bool loop = true; // 是否循环播放
    
    [Header("渲染组件")]
    public SpriteRenderer targetSpriteRenderer; // 目标SpriteRenderer组件
    public Image targetImage; // 目标UI Image组件
    public bool useGlobalRenderer = true; // 是否使用全局渲染器(如果为false,使用上面指定的组件)
    
    [Header("渲染设置")]
    public bool setNativeSize = false; // 是否设置为原始尺寸(仅对Image有效)
    public bool preserveAspect = true; // 是否保持宽高比(仅对Image有效)
    public Color tintColor = Color.white; // 着色颜色
    public Material overrideMaterial; // 覆盖材质
    
    [Header("变换设置")]
    public bool useCustomScale = false; // 是否使用自定义缩放
    public Vector3 customScale = Vector3.one; // 自定义缩放值
    public bool useCustomRotation = false; // 是否使用自定义旋转
    public Vector3 customRotation = Vector3.zero; // 自定义旋转值
    
    [Header("排序设置")]
    public bool overrideSortingOrder = false; // 是否覆盖排序层级
    public int sortingOrder = 0; // 排序层级
    public string sortingLayerName = "Default"; // 排序层名称
    
    [Header("曲线控制")]
    public AnimationCurve curve; // 动画曲线,用于控制播放速度
    public bool useCurve = false; // 是否使用曲线控制
    
    // 运行时数据(不序列化)
    [System.NonSerialized]
    private Vector3 originalScale;
    [System.NonSerialized]
    private Vector3 originalRotation;
    [System.NonSerialized]
    private Color originalColor;
    [System.NonSerialized]
    private Material originalMaterial;
    [System.NonSerialized]
    private int originalSortingOrder;
    [System.NonSerialized]
    private string originalSortingLayer;
    [System.NonSerialized]
    private bool hasStoredOriginalValues = false;
    
    // 构造函数
    public AnimationSequence()
    {
        curve = AnimationCurve.Linear(0f, 1f, 1f, 1f);
    }
    
    public AnimationSequence(string animName, Sprite[] animFrames, float rate = 30f, bool isLoop = true)
    {
        name = animName;
        frames = animFrames;
        framerate = rate;
        loop = isLoop;
        curve = AnimationCurve.Linear(0f, 1f, 1f, 1f);
    }
    
    /// <summary>
    /// 存储原始值(用于恢复)
    /// </summary>
    public void StoreOriginalValues(SpriteRenderer spriteRenderer, Image image)
    {
        if (hasStoredOriginalValues) return;
        
        if (!useGlobalRenderer)
        {
            if (targetSpriteRenderer != null)
                spriteRenderer = targetSpriteRenderer;
            if (targetImage != null)
                image = targetImage;
        }
        
        if (spriteRenderer != null)
        {
            originalScale = spriteRenderer.transform.localScale;
            originalRotation = spriteRenderer.transform.localEulerAngles;
            originalColor = spriteRenderer.color;
            originalMaterial = spriteRenderer.material;
            originalSortingOrder = spriteRenderer.sortingOrder;
            originalSortingLayer = spriteRenderer.sortingLayerName;
        }
        else if (image != null)
        {
            originalScale = image.transform.localScale;
            originalRotation = image.transform.localEulerAngles;
            originalColor = image.color;
            originalMaterial = image.material;
        }
        
        hasStoredOriginalValues = true;
    }
    
    /// <summary>
    /// 恢复原始值
    /// </summary>
    public void RestoreOriginalValues(SpriteRenderer spriteRenderer, Image image)
    {
        if (!hasStoredOriginalValues) return;
        
        if (!useGlobalRenderer)
        {
            if (targetSpriteRenderer != null)
                spriteRenderer = targetSpriteRenderer;
            if (targetImage != null)
                image = targetImage;
        }
        
        if (spriteRenderer != null)
        {
            spriteRenderer.transform.localScale = originalScale;
            spriteRenderer.transform.localEulerAngles = originalRotation;
            spriteRenderer.color = originalColor;
            spriteRenderer.material = originalMaterial;
            spriteRenderer.sortingOrder = originalSortingOrder;
            spriteRenderer.sortingLayerName = originalSortingLayer;
        }
        else if (image != null)
        {
            image.transform.localScale = originalScale;
            image.transform.localEulerAngles = originalRotation;
            image.color = originalColor;
            image.material = originalMaterial;
        }
    }
    
    /// <summary>
    /// 应用渲染设置
    /// </summary>
    public void ApplyRenderSettings(SpriteRenderer spriteRenderer, Image image)
    {
        if (!useGlobalRenderer)
        {
            if (targetSpriteRenderer != null)
                spriteRenderer = targetSpriteRenderer;
            if (targetImage != null)
                image = targetImage;
        }
        
        if (spriteRenderer != null)
        {
            // 应用颜色
            spriteRenderer.color = tintColor;
            
            // 应用材质
            if (overrideMaterial != null)
                spriteRenderer.material = overrideMaterial;
            
            // 应用排序设置
            if (overrideSortingOrder)
            {
                spriteRenderer.sortingOrder = sortingOrder;
                spriteRenderer.sortingLayerName = sortingLayerName;
            }
            
            // 应用变换设置
            if (useCustomScale)
                spriteRenderer.transform.localScale = customScale;
            if (useCustomRotation)
                spriteRenderer.transform.localEulerAngles = customRotation;
        }
        else if (image != null)
        {
            // 应用颜色
            image.color = tintColor;
            
            // 应用材质
            if (overrideMaterial != null)
                image.material = overrideMaterial;
            
            // 应用Image特有设置
            if (setNativeSize)
                image.SetNativeSize();
            image.preserveAspect = preserveAspect;
            
            // 应用变换设置
            if (useCustomScale)
                image.transform.localScale = customScale;
            if (useCustomRotation)
                image.transform.localEulerAngles = customRotation;
        }
    }
    
    /// <summary>
    /// 获取实际使用的SpriteRenderer
    /// </summary>
    public SpriteRenderer GetSpriteRenderer(SpriteRenderer defaultRenderer)
    {
        return useGlobalRenderer ? defaultRenderer : targetSpriteRenderer;
    }
    
    /// <summary>
    /// 获取实际使用的Image
    /// </summary>
    public Image GetImage(Image defaultImage)
    {
        return useGlobalRenderer ? defaultImage : targetImage;
    }
}

/// <summary>
/// 序列帧动画播放器
/// 支持SpriteRenderer和Image两种组件,支持多个动画序列
/// </summary>
public class SequenceFramePlayer : MonoBehaviour
{
    [Header("动画序列")]
    [SerializeField] private List<AnimationSequence> animations = new List<AnimationSequence>(); // 多个动画序列
    [SerializeField] private int defaultAnimationIndex = 0; // 默认播放的动画索引
    [SerializeField] private bool playOnStart = true; // 启动时自动播放
    [SerializeField] private bool ignoreTimeScale = false; // 是否忽略时间缩放
    
    [Header("渲染组件")]
    [SerializeField] private SpriteRenderer spriteRenderer; // SpriteRenderer组件
    [SerializeField] private Image image; // UI Image组件
    
    // 私有变量
    private int currentAnimationIndex = 0; // 当前播放的动画索引
    private int currentFrameIndex = 0;
    private float timer = 0f;
    private bool isPlaying = false;
    
    // 属性
    public bool IsPlaying => isPlaying;
    public int CurrentAnimationIndex => currentAnimationIndex;
    public string CurrentAnimationName => GetCurrentAnimation()?.name ?? "None";
    public int CurrentFrame => currentFrameIndex;
    public int TotalFrames => GetCurrentAnimation()?.frames?.Length ?? 0;
    public float Progress => TotalFrames > 0 ? (float)currentFrameIndex / TotalFrames : 0f;
    public int AnimationCount => animations?.Count ?? 0;
    
    // 事件
    public System.Action OnAnimationStart;
    public System.Action OnAnimationComplete;
    public System.Action<int> OnFrameChanged;
    public System.Action<int, string> OnAnimationChanged; // 动画切换事件 (索引, 名称)
    
    private void Awake()
    {
        // 自动获取组件
        if (spriteRenderer == null)
            spriteRenderer = GetComponent<SpriteRenderer>();
        if (image == null)
            image = GetComponent<Image>();
            
        // 初始化默认动画索引
        if (defaultAnimationIndex >= 0 && defaultAnimationIndex < animations.Count)
        {
            currentAnimationIndex = defaultAnimationIndex;
        }
    }
    
    private void Start()
    {
        if (playOnStart && HasValidAnimation())
        {
            Play();
        }
    }
    
    /// <summary>
    /// 获取当前动画序列
    /// </summary>
    private AnimationSequence GetCurrentAnimation()
    {
        if (animations == null || currentAnimationIndex < 0 || currentAnimationIndex >= animations.Count)
            return null;
        return animations[currentAnimationIndex];
    }
    
    /// <summary>
    /// 检查当前是否有有效的动画
    /// </summary>
    private bool HasValidAnimation()
    {
        var anim = GetCurrentAnimation();
        return anim != null && anim.frames != null && anim.frames.Length > 0;
    }
    
    private void Update()
    {
        if (!isPlaying || !HasValidAnimation())
            return;
            
        var currentAnim = GetCurrentAnimation();
        
        // 计算最终帧率
        float finalFramerate = currentAnim.framerate;
        
        if (currentAnim.useCurve && currentAnim.curve != null)
        {
            // 从曲线获取当前帧率
            float curveValue = currentAnim.curve.Evaluate((float)currentFrameIndex / currentAnim.frames.Length);
            finalFramerate = curveValue * currentAnim.framerate;
        }
        
        // 帧率有效(添加最小值保护)
        if (finalFramerate > 0.01f) // 最小帧率保护
        {
            // 获取当前时间
            float time = ignoreTimeScale ? Time.unscaledTime : Time.time;
            // 计算帧间隔时间
            float interval = 1.0f / finalFramerate;
            
            // 满足更新条件,执行更新操作
            if (time - timer > interval)
            {
                // 执行更新操作
                DoUpdate();
                timer = time;
            }
        }
        else
        {
            // 帧率过低时,使用默认帧率
            Debug.LogWarning($"Framerate too low ({finalFramerate}), using default framerate.");
            finalFramerate = 1f; // 使用1帧/秒作为最低帧率
            
            float time = ignoreTimeScale ? Time.unscaledTime : Time.time;
            float interval = 1.0f / finalFramerate;
            
            if (time - timer > interval)
            {
                DoUpdate();
                timer = time;
            }
        }
    }
    
    /// <summary>
    /// 执行帧更新
    /// </summary>
    private void DoUpdate()
    {
        var currentAnim = GetCurrentAnimation();
        if (currentAnim == null) return;
        
        // 更新帧索引
        currentFrameIndex++;
        
        // 检查是否播放完成
        if (currentFrameIndex >= currentAnim.frames.Length)
        {
            if (currentAnim.loop)
            {
                currentFrameIndex = 0; // 循环播放
            }
            else
            {
                currentFrameIndex = currentAnim.frames.Length - 1;
                Stop();
                OnAnimationComplete?.Invoke();
                return;
            }
        }
        
        // 更新显示的帧
        UpdateFrame();
        
        // 触发帧变化事件
        OnFrameChanged?.Invoke(currentFrameIndex);
    }
    
    /// <summary>
    /// 更新当前显示的帧
    /// </summary>
    private void UpdateFrame()
    {
        var currentAnim = GetCurrentAnimation();
        if (currentAnim?.frames == null || currentFrameIndex < 0 || currentFrameIndex >= currentAnim.frames.Length)
            return;
            
        Sprite currentSprite = currentAnim.frames[currentFrameIndex];
        
        // 获取实际使用的渲染组件
        SpriteRenderer targetSpriteRenderer = currentAnim.GetSpriteRenderer(spriteRenderer);
        Image targetImage = currentAnim.GetImage(image);
        
        // 更新SpriteRenderer
        if (targetSpriteRenderer != null)
        {
            targetSpriteRenderer.sprite = currentSprite;
        }
        
        // 更新Image
        if (targetImage != null)
        {
            targetImage.sprite = currentSprite;
        }
    }
    
    /// <summary>
    /// 开始播放当前动画
    /// </summary>
    public void Play()
    {
        if (!HasValidAnimation())
        {
            Debug.LogWarning("No valid animation to play!");
            return;
        }
        
        // 应用当前动画的渲染设置
        var currentAnim = GetCurrentAnimation();
        if (currentAnim != null)
        {
            currentAnim.StoreOriginalValues(spriteRenderer, image);
            currentAnim.ApplyRenderSettings(spriteRenderer, image);
        }
        
        isPlaying = true;
        timer = ignoreTimeScale ? Time.unscaledTime : Time.time;
        UpdateFrame();
        OnAnimationStart?.Invoke();
    }
    
    /// <summary>
    /// 播放指定索引的动画
    /// </summary>
    public void PlayAnimation(int animationIndex)
    {
        if (SetAnimation(animationIndex))
        {
            Play();
        }
    }
    
    /// <summary>
    /// 播放指定名称的动画
    /// </summary>
    public void PlayAnimation(string animationName)
    {
        int index = GetAnimationIndex(animationName);
        if (index >= 0)
        {
            PlayAnimation(index);
        }
        else
        {
            Debug.LogWarning($"Animation '{animationName}' not found!");
        }
    }
    
    /// <summary>
    /// 停止播放
    /// </summary>
    public void Stop()
    {
        isPlaying = false;
    }
    
    /// <summary>
    /// 暂停播放
    /// </summary>
    public void Pause()
    {
        isPlaying = false;
    }
    
    /// <summary>
    /// 重置到第一帧
    /// </summary>
    public void Reset()
    {
        currentFrameIndex = 0;
        UpdateFrame();
    }
    
    /// <summary>
    /// 跳转到指定帧
    /// </summary>
    public void SetFrame(int frameIndex)
    {
        var currentAnim = GetCurrentAnimation();
        if (currentAnim?.frames == null || frameIndex < 0 || frameIndex >= currentAnim.frames.Length)
            return;
            
        currentFrameIndex = frameIndex;
        UpdateFrame();
        OnFrameChanged?.Invoke(currentFrameIndex);
    }
    
    /// <summary>
    /// 设置当前动画
    /// </summary>
    public bool SetAnimation(int animationIndex)
    {
        if (animations == null || animationIndex < 0 || animationIndex >= animations.Count)
        {
            Debug.LogWarning($"Invalid animation index: {animationIndex}");
            return false;
        }
        
        if (currentAnimationIndex != animationIndex)
        {
            // 恢复之前动画的设置
            var previousAnim = GetCurrentAnimation();
            if (previousAnim != null)
            {
                previousAnim.RestoreOriginalValues(spriteRenderer, image);
            }
            
            // 切换到新动画
            currentAnimationIndex = animationIndex;
            
            // 存储并应用新动画的设置
            var newAnim = GetCurrentAnimation();
            if (newAnim != null)
            {
                newAnim.StoreOriginalValues(spriteRenderer, image);
                newAnim.ApplyRenderSettings(spriteRenderer, image);
            }
            
            Reset();
            OnAnimationChanged?.Invoke(currentAnimationIndex, CurrentAnimationName);
        }
        return true;
    }
    
    /// <summary>
    /// 设置当前动画(通过名称)
    /// </summary>
    public bool SetAnimation(string animationName)
    {
        int index = GetAnimationIndex(animationName);
        if (index >= 0)
        {
            return SetAnimation(index);
        }
        return false;
    }
    
    /// <summary>
    /// 获取动画索引(通过名称)
    /// </summary>
    public int GetAnimationIndex(string animationName)
    {
        if (animations == null) return -1;
        
        for (int i = 0; i < animations.Count; i++)
        {
            if (animations[i].name == animationName)
                return i;
        }
        return -1;
    }
    
    /// <summary>
    /// 添加新的动画序列
    /// </summary>
    public void AddAnimation(AnimationSequence newAnimation)
    {
        if (animations == null)
            animations = new List<AnimationSequence>();
        animations.Add(newAnimation);
    }
    
    /// <summary>
    /// 添加新的动画序列
    /// </summary>
    public void AddAnimation(string name, Sprite[] frames, float framerate = 30f, bool loop = true)
    {
        AddAnimation(new AnimationSequence(name, frames, framerate, loop));
    }
    
    /// <summary>
    /// 移除动画序列
    /// </summary>
    public bool RemoveAnimation(int index)
    {
        if (animations == null || index < 0 || index >= animations.Count)
            return false;
            
        animations.RemoveAt(index);
        
        // 调整当前动画索引
        if (currentAnimationIndex >= animations.Count)
        {
            currentAnimationIndex = Mathf.Max(0, animations.Count - 1);
        }
        return true;
    }
    
    /// <summary>
    /// 移除动画序列
    /// </summary>
    public bool RemoveAnimation(string animationName)
    {
        int index = GetAnimationIndex(animationName);
        return index >= 0 && RemoveAnimation(index);
    }
    
    /// <summary>
    /// 获取所有动画名称
    /// </summary>
    public string[] GetAnimationNames()
    {
        if (animations == null) return new string[0];
        
        string[] names = new string[animations.Count];
        for (int i = 0; i < animations.Count; i++)
        {
            names[i] = animations[i].name;
        }
        return names;
    }
    
    /// <summary>
    /// 获取当前动画使用的SpriteRenderer
    /// </summary>
    public SpriteRenderer GetCurrentSpriteRenderer()
    {
        var currentAnim = GetCurrentAnimation();
        return currentAnim?.GetSpriteRenderer(spriteRenderer);
    }
    
    /// <summary>
    /// 获取当前动画使用的Image
    /// </summary>
    public Image GetCurrentImage()
    {
        var currentAnim = GetCurrentAnimation();
        return currentAnim?.GetImage(image);
    }
    
    /// <summary>
    /// 设置当前动画的渲染颜色
    /// </summary>
    public void SetCurrentAnimationColor(Color color)
    {
        var currentAnim = GetCurrentAnimation();
        if (currentAnim != null)
        {
            currentAnim.tintColor = color;
            
            // 立即应用
            SpriteRenderer targetSpriteRenderer = currentAnim.GetSpriteRenderer(spriteRenderer);
            Image targetImage = currentAnim.GetImage(image);
            
            if (targetSpriteRenderer != null)
                targetSpriteRenderer.color = color;
            if (targetImage != null)
                targetImage.color = color;
        }
    }
    
    /// <summary>
    /// 设置当前动画的排序层级
    /// </summary>
    public void SetCurrentAnimationSortingOrder(int order)
    {
        var currentAnim = GetCurrentAnimation();
        if (currentAnim != null)
        {
            currentAnim.sortingOrder = order;
            currentAnim.overrideSortingOrder = true;
            
            // 立即应用
            SpriteRenderer targetSpriteRenderer = currentAnim.GetSpriteRenderer(spriteRenderer);
            if (targetSpriteRenderer != null)
                targetSpriteRenderer.sortingOrder = order;
        }
    }
    
    /// <summary>
    /// 设置当前动画的缩放
    /// </summary>
    public void SetCurrentAnimationScale(Vector3 scale)
    {
        var currentAnim = GetCurrentAnimation();
        if (currentAnim != null)
        {
            currentAnim.customScale = scale;
            currentAnim.useCustomScale = true;
            
            // 立即应用
            SpriteRenderer targetSpriteRenderer = currentAnim.GetSpriteRenderer(spriteRenderer);
            Image targetImage = currentAnim.GetImage(image);
            
            if (targetSpriteRenderer != null)
                targetSpriteRenderer.transform.localScale = scale;
            if (targetImage != null)
                targetImage.transform.localScale = scale;
        }
    }
    
    /// <summary>
    /// 为指定动画设置目标渲染组件
    /// </summary>
    public void SetAnimationRenderer(int animationIndex, SpriteRenderer targetRenderer, Image targetImg = null)
    {
        if (animations == null || animationIndex < 0 || animationIndex >= animations.Count)
            return;
            
        animations[animationIndex].targetSpriteRenderer = targetRenderer;
        animations[animationIndex].targetImage = targetImg;
        animations[animationIndex].useGlobalRenderer = (targetRenderer == null && targetImg == null);
    }
    
    /// <summary>
    /// 为指定动画设置目标渲染组件(通过名称)
    /// </summary>
    public void SetAnimationRenderer(string animationName, SpriteRenderer targetRenderer, Image targetImg = null)
    {
        int index = GetAnimationIndex(animationName);
        if (index >= 0)
        {
            SetAnimationRenderer(index, targetRenderer, targetImg);
        }
    }
    
    /// <summary>
    /// 启用/禁用组件
    /// </summary>
    private void OnEnable()
    {
        if (playOnStart && HasValidAnimation())
        {
            Play();
        }
    }
    
    private void OnDisable()
    {
        Stop();
        
        // 恢复原始设置
        var currentAnim = GetCurrentAnimation();
        if (currentAnim != null)
        {
            currentAnim.RestoreOriginalValues(spriteRenderer, image);
        }
    }
} 

SequenceFramePlayerExample

using System.Collections;
using UnityEngine;
using UnityEngine.UI;

/// <summary>
/// SequenceFramePlayer 使用示例
/// </summary>
public class SequenceFramePlayerExample : MonoBehaviour
{
    [Header("示例组件")]
    public SequenceFramePlayer framePlayer;
    public SpriteRenderer backgroundRenderer;
    public SpriteRenderer characterRenderer;
    public Image uiImage;
    
    [Header("示例序列帧")]
    public Sprite[] idleFrames;
    public Sprite[] walkFrames;
    public Sprite[] attackFrames;
    public Sprite[] uiFrames;
    
    private void Start()
    {
        // 示例1:基础使用
        BasicUsageExample();
        
        // 示例2:多渲染器使用
        MultiRendererExample();
        
        // 示例3:运行时动态管理
        RuntimeManagementExample();
        
        // 示例4:事件监听
        EventListenerExample();
    }
    
    /// <summary>
    /// 示例1:基础使用 - 简单播放动画
    /// </summary>
    void BasicUsageExample()
    {
        Debug.Log("=== 基础使用示例 ===");
        
        // 直接播放当前动画(默认第0个)
        framePlayer.Play();
        
        // 播放指定索引的动画
        framePlayer.PlayAnimation(1);
        
        // 播放指定名称的动画
        framePlayer.PlayAnimation("idle");
        
        // 控制播放
        StartCoroutine(BasicPlaybackControl());
    }
    
    IEnumerator BasicPlaybackControl()
    {
        yield return new WaitForSeconds(2f);
        
        // 暂停
        framePlayer.Pause();
        Debug.Log("动画暂停");
        
        yield return new WaitForSeconds(1f);
        
        // 继续播放
        framePlayer.Play();
        Debug.Log("动画继续");
        
        yield return new WaitForSeconds(2f);
        
        // 跳转到指定帧
        framePlayer.SetFrame(5);
        Debug.Log("跳转到第5帧");
        
        yield return new WaitForSeconds(1f);
        
        // 重置到第一帧
        framePlayer.Reset();
        Debug.Log("重置到第一帧");
    }
    
    /// <summary>
    /// 示例2:多渲染器使用 - 不同动画渲染到不同组件
    /// </summary>
    void MultiRendererExample()
    {
        Debug.Log("=== 多渲染器示例 ===");
        
        // 为不同动画设置不同的渲染器
        framePlayer.SetAnimationRenderer("background", backgroundRenderer);
        framePlayer.SetAnimationRenderer("character", characterRenderer);
        framePlayer.SetAnimationRenderer("ui", null, uiImage); // UI动画渲染到Image
        
        // 播放背景动画
        framePlayer.PlayAnimation("background");
        
        StartCoroutine(SwitchRenderers());
    }
    
    IEnumerator SwitchRenderers()
    {
        yield return new WaitForSeconds(3f);
        
        // 切换到角色动画(会自动切换到characterRenderer)
        framePlayer.PlayAnimation("character");
        Debug.Log("切换到角色动画");
        
        yield return new WaitForSeconds(3f);
        
        // 切换到UI动画(会自动切换到uiImage)
        framePlayer.PlayAnimation("ui");
        Debug.Log("切换到UI动画");
    }
    
    /// <summary>
    /// 示例3:运行时动态管理 - 动态添加、修改动画
    /// </summary>
    void RuntimeManagementExample()
    {
        Debug.Log("=== 运行时管理示例 ===");
        
        // 运行时添加新动画
        if (idleFrames != null && idleFrames.Length > 0)
        {
            framePlayer.AddAnimation("runtime_idle", idleFrames, 24f, true);
            Debug.Log("添加了运行时空闲动画");
        }
        
        if (walkFrames != null && walkFrames.Length > 0)
        {
            framePlayer.AddAnimation("runtime_walk", walkFrames, 30f, true);
            Debug.Log("添加了运行时行走动画");
        }
        
        // 获取所有动画名称
        string[] animNames = framePlayer.GetAnimationNames();
        Debug.Log($"当前动画数量: {animNames.Length}");
        foreach (string name in animNames)
        {
            Debug.Log($"动画: {name}");
        }
        
        StartCoroutine(RuntimeDynamicControl());
    }
    
    IEnumerator RuntimeDynamicControl()
    {
        yield return new WaitForSeconds(1f);
        
        // 播放运行时添加的动画
        framePlayer.PlayAnimation("runtime_idle");
        Debug.Log("播放运行时空闲动画");
        
        yield return new WaitForSeconds(2f);
        
        // 动态修改当前动画的颜色
        framePlayer.SetCurrentAnimationColor(Color.red);
        Debug.Log("设置动画颜色为红色");
        
        yield return new WaitForSeconds(1f);
        
        // 动态修改当前动画的缩放
        framePlayer.SetCurrentAnimationScale(new Vector3(1.5f, 1.5f, 1f));
        Debug.Log("设置动画缩放为1.5倍");
        
        yield return new WaitForSeconds(1f);
        
        // 动态修改排序层级
        framePlayer.SetCurrentAnimationSortingOrder(10);
        Debug.Log("设置排序层级为10");
        
        yield return new WaitForSeconds(2f);
        
        // 切换到其他动画(会自动恢复原始设置)
        framePlayer.PlayAnimation("runtime_walk");
        Debug.Log("切换到行走动画(自动恢复设置)");
    }
    
    /// <summary>
    /// 示例4:事件监听 - 监听动画事件
    /// </summary>
    void EventListenerExample()
    {
        Debug.Log("=== 事件监听示例 ===");
        
        // 监听动画开始事件
        framePlayer.OnAnimationStart += () => {
            Debug.Log($"动画开始播放: {framePlayer.CurrentAnimationName}");
        };
        
        // 监听动画完成事件
        framePlayer.OnAnimationComplete += () => {
            Debug.Log($"动画播放完成: {framePlayer.CurrentAnimationName}");
            OnAnimationCompleted();
        };
        
        // 监听帧变化事件
        framePlayer.OnFrameChanged += (frameIndex) => {
            Debug.Log($"当前帧: {frameIndex}/{framePlayer.TotalFrames},进度: {framePlayer.Progress:P1}");
        };
        
        // 监听动画切换事件
        framePlayer.OnAnimationChanged += (index, name) => {
            Debug.Log($"动画切换: 索引 {index},名称 '{name}'");
            OnAnimationSwitched(index, name);
        };
    }
    
    void OnAnimationCompleted()
    {
        // 动画完成后的逻辑
        Debug.Log("执行动画完成后的逻辑");
    }
    
    void OnAnimationSwitched(int index, string name)
    {
        // 动画切换后的逻辑
        Debug.Log($"动画已切换到: {name}");
        
        // 获取当前使用的渲染组件
        SpriteRenderer currentSpriteRenderer = framePlayer.GetCurrentSpriteRenderer();
        Image currentImage = framePlayer.GetCurrentImage();
        
        if (currentSpriteRenderer != null)
            Debug.Log($"当前使用SpriteRenderer: {currentSpriteRenderer.name}");
        if (currentImage != null)
            Debug.Log($"当前使用Image: {currentImage.name}");
    }
    
    /// <summary>
    /// 键盘控制示例
    /// </summary>
    void Update()
    {
        // 数字键1-4控制动画播放
        if (Input.GetKeyDown(KeyCode.Alpha1))
        {
            framePlayer.PlayAnimation(0);
            Debug.Log("播放动画 0");
        }
        if (Input.GetKeyDown(KeyCode.Alpha2))
        {
            framePlayer.PlayAnimation(1);
            Debug.Log("播放动画 1");
        }
        if (Input.GetKeyDown(KeyCode.Alpha3))
        {
            framePlayer.PlayAnimation(2);
            Debug.Log("播放动画 2");
        }
        if (Input.GetKeyDown(KeyCode.Alpha4))
        {
            framePlayer.PlayAnimation(3);
            Debug.Log("播放动画 3");
        }
        
        // 空格键暂停/播放
        if (Input.GetKeyDown(KeyCode.Space))
        {
            if (framePlayer.IsPlaying)
            {
                framePlayer.Pause();
                Debug.Log("暂停动画");
            }
            else
            {
                framePlayer.Play();
                Debug.Log("继续动画");
            }
        }
        
        // R键重置
        if (Input.GetKeyDown(KeyCode.R))
        {
            framePlayer.Reset();
            Debug.Log("重置动画");
        }
        
        // C键改变颜色
        if (Input.GetKeyDown(KeyCode.C))
        {
            Color randomColor = new Color(Random.value, Random.value, Random.value, 1f);
            framePlayer.SetCurrentAnimationColor(randomColor);
            Debug.Log($"设置随机颜色: {randomColor}");
        }
        
        // S键改变缩放
        if (Input.GetKeyDown(KeyCode.S))
        {
            float scale = Random.Range(0.5f, 2f);
            framePlayer.SetCurrentAnimationScale(Vector3.one * scale);
            Debug.Log($"设置缩放: {scale}");
        }
    }
    
    /// <summary>
    /// 高级用法示例 - 创建复杂的动画序列
    /// </summary>
    public void AdvancedUsageExample()
    {
        Debug.Log("=== 高级用法示例 ===");
        
        // 创建一个复杂的动画序列
        var complexAnim = new AnimationSequence();
        complexAnim.name = "complex_animation";
        complexAnim.frames = attackFrames;
        complexAnim.framerate = 60f;
        complexAnim.loop = false;
        
        // 设置渲染属性
        complexAnim.useGlobalRenderer = false;
        complexAnim.targetSpriteRenderer = characterRenderer;
        complexAnim.tintColor = Color.yellow;
        complexAnim.useCustomScale = true;
        complexAnim.customScale = new Vector3(2f, 2f, 1f);
        complexAnim.overrideSortingOrder = true;
        complexAnim.sortingOrder = 100;
        
        // 设置曲线控制
        complexAnim.useCurve = true;
        complexAnim.curve = AnimationCurve.EaseInOut(0f, 0.5f, 1f, 2f); // 先慢后快
        
        // 添加到播放器
        framePlayer.AddAnimation(complexAnim);
        
        // 播放这个复杂动画
        framePlayer.PlayAnimation("complex_animation");
    }
}