Unity编辑器脚本:两个动画轨道,间隔180帧替换1组图片,按顺序执行

Unity编辑器脚本。这个脚本会在两个动画轨道上交替添加来自两个路径的序列帧,每个关键帧间隔180帧(3秒,假设帧率60帧/秒):

#if UNITY_EDITOR
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEditor;
using System.Text.RegularExpressions;
using UnityEngine.Animations;

public class SequenceAnimator : EditorWindow
{
    private string pathA = "Assets/Sprites/PathA";
    private string pathB = "Assets/Sprites/PathB";
    private AnimationClip animationClip;
    private GameObject targetObject;
    private int frameInterval = 180;

    [MenuItem("Window/Animation/Sequence Frame Creator")]
    public static void ShowWindow()
    {
        GetWindow<SequenceAnimator>("Frame Sequencer");
    }

    void OnGUI()
    {
        GUILayout.Label("Sequence Frame Settings", EditorStyles.boldLabel);
        
        targetObject = (GameObject)EditorGUILayout.ObjectField("Target Object", targetObject, typeof(GameObject), true);
        animationClip = (AnimationClip)EditorGUILayout.ObjectField("Animation Clip", animationClip, typeof(AnimationClip), false);
        
        pathA = EditorGUILayout.TextField("Path A:", pathA);
        pathB = EditorGUILayout.TextField("Path B:", pathB);
        
        frameInterval = EditorGUILayout.IntField("Frame Interval:", frameInterval);

        if (GUILayout.Button("Generate Animation"))
        {
            if (targetObject == null || animationClip == null)
            {
                Debug.LogError("Please assign Target Object and Animation Clip!");
                return;
            }
            
            GenerateAnimationSequence();
        }
    }

    void GenerateAnimationSequence()
    {
        var spritesA = GetSortedSprites(pathA);
        var spritesB = GetSortedSprites(pathB);

        if (spritesA.Count == 0 || spritesB.Count == 0)
        {
            Debug.LogError("No sprites found in one of the paths!");
            return;
        }

        if (spritesA.Count != spritesB.Count)
        {
            Debug.LogError("Sprite counts in both paths don't match!");
            return;
        }

        // 创建两个动画轨道
        CreateTrack("TrackA", spritesA, 0);
        CreateTrack("TrackB", spritesB, frameInterval/2);
    }

    void CreateTrack(string trackName, List<Sprite> sprites, int offset)
    {
        AnimationClipSettings settings = AnimationUtility.GetAnimationClipSettings(animationClip);
        float frameRate = settings.frameRate == 0 ? 60 : settings.frameRate;
        
        var binding = new EditorCurveBinding
        {
            path = "",  // 根路径
            type = typeof(SpriteRenderer),
            propertyName = "m_Sprite"
        };

        List<ObjectReferenceKeyframe> keyFrames = new List<ObjectReferenceKeyframe>();

        for (int i = 0; i < sprites.Count; i++)
        {
            float time = (i * frameInterval + offset) / frameRate;
            
            keyFrames.Add(new ObjectReferenceKeyframe
            {
                time = time,
                value = sprites[i]
            });
        }

        AnimationUtility.SetObjectReferenceCurve(animationClip, binding, keyFrames.ToArray());
    }

    List<Sprite> GetSortedSprites(string path)
    {
        List<Sprite> sprites = new List<Sprite>();
        
        string[] guids = AssetDatabase.FindAssets("t:Sprite", new[] { path });
        foreach (string guid in guids)
        {
            string assetPath = AssetDatabase.GUIDToAssetPath(guid);
            Sprite sprite = AssetDatabase.LoadAssetAtPath<Sprite>(assetPath);
            if (sprite != null)
            {
                sprites.Add(sprite);
            }
        }

        // 自然排序
        return sprites.OrderBy(s => 
            Regex.Replace(s.name, @"\d+", m => m.Value.PadLeft(10, '0')))
            .ToList();
    }
}
#endif

使用方法:

  1. 通过菜单 Window > Animation > Sequence Frame Creator 打开窗口
  2. 指定目标物体(需要有SpriteRenderer组件)
  3. 创建或指定一个Animation Clip
  4. 输入两个图片路径(相对于Assets的路径)
  5. 点击Generate Animation按钮

特性说明:

  1. 自动检测两个路径下的所有Sprite资源
  2. 支持自然排序(能正确处理类似frame1, frame2,…, frame10的序列)
  3. 自动创建两个动画轨道,每个轨道间隔90帧(总间隔180帧)
  4. 自动处理时间计算(基于动画剪辑的帧率)

注意:

  1. 确保目标GameObject上有SpriteRenderer组件
  2. 图片需要设置为Sprite类型(在Import Settings里设置)
  3. 路径需要是Assets下的相对路径
  4. 动画剪辑建议设置为可循环播放模式
  5. 可以通过调整frameInterval参数修改关键帧间隔

这个脚本会在同一个SpriteRenderer组件上创建两个动画曲线轨道,通过交替显示两个路径的Sprite来达到组合动画的效果。第一个路径的帧会在0帧、180帧、360帧等位置,第二个路径的帧会在90帧、270帧、450帧等位置显示。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值