美文网首页
代码创建帧动画实现

代码创建帧动画实现

作者: braveheart_ | 来源:发表于2018-08-19 01:40 被阅读0次
    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已验证可行

    相关文章

      网友评论

          本文标题:代码创建帧动画实现

          本文链接:https://www.haomeiwen.com/subject/esiqiftx.html