代码创建帧动画实现

2018-08-19  本文已影响0人  braveheart_
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.Linq;
using System.Text.RegularExpressions;
using System.IO;
using UnityEngine.UI;
using UnityEditor.Animations;

public class SpriteAnimationCreator : MonoBehaviour
{
    //默认帧间隔
    private static float defaultInterval = 0.1f;

    [MenuItem("MyTest/Create/SpriteAnimation")]
    public static void Create()
    {
        //获取project面板中选中的sprite
        List<Sprite> selectedSprites = new List<Sprite>(Selection.GetFiltered(typeof(Sprite), SelectionMode.DeepAssets).OfType<Sprite>());

        //如果选中了纹理则获取精灵
        Object[] selectedTextures = Selection.GetFiltered(typeof(Texture2D), SelectionMode.DeepAssets);

        foreach(Object texture in selectedTextures)
        {
            selectedSprites.AddRange(AssetDatabase.LoadAllAssetsAtPath(AssetDatabase.GetAssetPath(texture)).OfType<Sprite>());
        }

        if(selectedSprites.Count < 1)
        {
            Debug.LogWarning("no sprite selected...");
            return;
        }

        //按照精灵末尾的连续编号进行排序
        string suffixPattern = "_?([0-9]+)$";
        selectedSprites.Sort((Sprite ls, Sprite rs)=>
        {
            Match lsMatch = Regex.Match(ls.name, suffixPattern);
            Match rsMatch = Regex.Match(rs.name, suffixPattern);
            if (lsMatch.Success && rsMatch.Success)
            {
                return (int.Parse(lsMatch.Groups[1].Value) - int.Parse(rsMatch.Groups[1].Value));
            }
            else
            {
                return ls.name.CompareTo(rs.name);
            }
        });

        //后续将资源保存在第一个精灵所在文件夹
        string baseDir = Path.GetDirectoryName(AssetDatabase.GetAssetPath(selectedSprites[0]));
        //将第一个精灵的不含连续编号的名称设置为动画的名称
        string baseName = Regex.Replace(selectedSprites[0].name, suffixPattern, "");
        if (string.IsNullOrEmpty(baseName))
        {
            baseName = selectedSprites[0].name;
        }

        //没有画布的话创建一个画布
        Canvas canvas = FindObjectOfType<Canvas>();
        if (canvas == null)
        {
            GameObject canvasObj = new GameObject("CanvasSpriteAnimation");
            canvas = canvasObj.AddComponent<Canvas>();
            canvas.renderMode = RenderMode.ScreenSpaceOverlay;
            canvasObj.AddComponent<CanvasScaler>();
            canvasObj.AddComponent<GraphicRaycaster>();
            canvasObj.layer = LayerMask.NameToLayer("UI");
        }

        //创建图像
        GameObject obj = new GameObject(baseName);
        obj.transform.parent = canvas.transform;
        obj.transform.localPosition = Vector3.zero;

        Image image = obj.AddComponent<Image>();
        image.sprite = selectedSprites[0];
        image.SetNativeSize();

        //添加animator
        Animator animator = obj.AddComponent<Animator>();

        //创建动画剪辑
        AnimationClip animationClip = AnimatorController.AllocateAnimatorClip(baseName);

        //使用EditorCurveBinding将关键帧和图像的Sprite属性进行关联
        EditorCurveBinding editorCurveBinding = new EditorCurveBinding();
        editorCurveBinding.type = typeof(Image);
        editorCurveBinding.path = "";
        editorCurveBinding.propertyName = "m_Sprite";

        //创建关键帧,数量为所选中的精灵数量,为各关键帧分配精灵
        ObjectReferenceKeyframe[] keyFrames = new ObjectReferenceKeyframe[selectedSprites.Count];
        for (int i = 0; i < selectedSprites.Count; i++)
        {
            keyFrames[i] = new ObjectReferenceKeyframe();
            keyFrames[i].time = i * defaultInterval;
            keyFrames[i].value = selectedSprites[i];
        }

        AnimationUtility.SetObjectReferenceCurve(animationClip, editorCurveBinding, keyFrames);

        //由于Loop Time属性无法直接从脚本中进行设置 因此使用SerializedProperty进行设置
        SerializedObject serializedAnimationClip = new SerializedObject(animationClip);
        SerializedProperty serializedAnimationClipSettings = serializedAnimationClip.FindProperty("m_AnimationClipSettings");
        serializedAnimationClipSettings.FindPropertyRelative("m_LoopTime").boolValue = true;
        serializedAnimationClip.ApplyModifiedProperties();

        //将创建的动画剪辑作为资源保存
        SaveAsset(animationClip, baseDir + "/" + baseName + ".anim");

        //创建动画控制器
        AnimatorController animatorController = AnimatorController.CreateAnimatorControllerAtPathWithClip(baseDir + "/" + baseName + ".controller", animationClip);
        animator.runtimeAnimatorController = animatorController;
    }

    private static void SaveAsset(Object obj, string path)
    {
        Object existingAsset = AssetDatabase.LoadMainAssetAtPath(path);
        if (existingAsset != null)
        {
            EditorUtility.CopySerialized(obj, existingAsset);
            AssetDatabase.SaveAssets();
        }
        else
        {
            AssetDatabase.CreateAsset(obj, path);
        }
    }
}

//移植《Unity UI 设计与开发从入门到精通》书本上代码运行思考并记录
//unity 2018已验证可行

上一篇下一篇

猜你喜欢

热点阅读