指定一个目标物体(有SpriteRenderer组件),30帧显示A中的1图,60帧显示B中的1图,90帧显示A中的2图,120帧显示B中的2图。。。依次间隔30帧交替,直到所有序列图全部打上关键帧。

以下是实现上述功能的Unity编辑器脚本:

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

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

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

    void OnGUI()
    {
        GUILayout.Label("Alternate 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;
        }

        // 获取目标物体的SpriteRenderer
        var spriteRenderer = targetObject.GetComponent<SpriteRenderer>();
        if (spriteRenderer == null)
        {
            Debug.LogError("Target object must have a SpriteRenderer component!");
            return;
        }

        // 计算帧率
        float frameRate = animationClip.frameRate > 0 ? animationClip.frameRate : 60f;

        // 获取物体在层级中的路径
        string relativePath = AnimationUtility.CalculateTransformPath(
            targetObject.transform, 
            FindRootTransform(targetObject.transform)
        );

        var binding = new EditorCurveBinding
        {
            path = relativePath,
            type = typeof(SpriteRenderer),
            propertyName = "m_Sprite"
        };

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

        // 交替添加A和B的图片
        for (int i = 0; i < spritesA.Count; i++)
        {
            // A的图片在偶数间隔
            float timeA = (i * 2 * frameInterval) / frameRate;
            keyFrames.Add(new ObjectReferenceKeyframe
            {
                time = timeA,
                value = spritesA[i]
            });

            // B的图片在奇数间隔
            float timeB = ((i * 2 + 1) * frameInterval) / frameRate;
            keyFrames.Add(new ObjectReferenceKeyframe
            {
                time = timeB,
                value = spritesB[i]
            });
        }

        AnimationUtility.SetObjectReferenceCurve(animationClip, binding, keyFrames.ToArray());
        EditorUtility.SetDirty(animationClip);
        AssetDatabase.SaveAssets();
        Debug.Log("Animation sequence generated successfully!");
    }

    Transform FindRootTransform(Transform t)
    {
        while (t.parent != null)
        {
            t = t.parent;
        }
        return t;
    }

    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. 指定路径:可以分别指定路径A和路径B,分别获取两组图片序列。
  2. 帧间隔设置:可以通过Frame Interval参数设置每两张图片之间的帧数间隔,默认为30帧。
  3. 交替显示:在同一个目标物体的SpriteRenderer中,交替显示路径A和路径B的图片。A的图片显示在0, 60, 120, ...帧,B的图片显示在30, 90, 150, ...帧。
  4. 自然排序:自动对图片文件进行自然排序,确保按正确顺序加载序列图片。

使用方法:

  1. 通过菜单 Window > Animation > Alternate Frame Creator 打开窗口。
  2. 指定带有SpriteRenderer组件的目标物体。
  3. 创建或选择一个Animation Clip
  4. 输入路径A和路径B(相对于Assets的路径)。
  5. 调整Frame Interval为所需的帧间隔(默认为30)。
  6. 点击Generate Animation按钮生成动画。

注意事项:

  1. 确保路径正确:路径A和路径B中的图片数量必须相同,且格式一致(如img1, img2, ...)。
  2. 动画剪辑设置:建议在生成后检查动画剪辑的帧率和循环设置。
  3. Sprite设置:确保图片被正确导入为Sprite类型,且Pivot设置正确。

这个脚本将帮助你高效地为同一个目标物体创建交替显示两组序列图片的动画,节省手动设置关键帧的时间。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值