[Unity编辑器] 根据图片自动生成动画

根据自己的情况 仿照 雨松MOMO 写了一个自动生成动画的脚本 原地址 http://www.xuanyusong.com/archives/3243

 

代码:

 

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using System;
using System.IO;
using UnityEditor.Animations;

public enum Orientation
{
    Down = 1, RightDown, Right, RightUp, Up, LeftUp, Left, LeftDown
}

public class BuildAnimation : Editor 
{
    #region 常量
    #endregion

    #region 事件
    #endregion

    #region 字段
    private static string m_prefabPath = "Assets/Resources/Prefabs";
    private static string m_AnimationControllerPath = "Assets/AnimationController";
    private static string m_animationPath = "Assets/Animation";
    private static string m_rawImagePath = Application.dataPath + "/Raw";
    #endregion

    #region 属性
    #endregion

    #region 方法
    [MenuItem("Assets/BuildAnimation")]
    static void BuildAnimations() {
        DirectoryInfo raw = new DirectoryInfo(m_rawImagePath);
        foreach (DirectoryInfo directories in raw.GetDirectories())
        {
            List clips = new List();
            foreach (DirectoryInfo ActionList in directories.GetDirectories())
            {
                List clipList = BuildAnimationList(ActionList);
                foreach (AnimationClip clip in clipList)
                {
                    clips.Add(clip);
                }
            }
            AnimatorController controller = BuildAnimationController(clips, directories.Name);
            BuildPrefab(directories, controller);
        }

    }

    /// 
    /// Build预设
    /// 
    /// 
    /// 
    private static void BuildPrefab(DirectoryInfo directories, AnimatorController animatorController)
    {
        FileInfo _image = directories.GetDirectories()[0].GetFiles("*.png")[0];
        GameObject _go = new GameObject();
        _go.name = directories.Name;
        SpriteRenderer _spriteRenderer = _go.AddComponent();
        _spriteRenderer.sprite = AssetDatabase.LoadAssetAtPath(DataPathToAssetPath(_image.FullName));

        Animator _animator = _go.AddComponent();
        _animator.runtimeAnimatorController = animatorController;

        System.IO.Directory.CreateDirectory(m_prefabPath);
        PrefabUtility.CreatePrefab(m_prefabPath + "/" + _go.name + ".prefab", _go);
        DestroyImmediate(_go);
    }

    /// 
    /// Build控制器
    /// 
    /// 
    /// 
    /// 
    private static AnimatorController BuildAnimationController(List clips, string name)
    {
        //string _parentName = System.IO.Directory.GetParent(directories.FullName).Name;
        //创建文件夹
        System.IO.Directory.CreateDirectory(m_AnimationControllerPath);
        AnimatorController animatorController = AnimatorController.
            CreateAnimatorControllerAtPath(m_AnimationControllerPath + "/" + name + ".controller");
        AnimatorControllerLayer layer = animatorController.layers[0];
        AnimatorStateMachine sm = layer.stateMachine;
        foreach (AnimationClip newClip in clips)
        {
            AnimatorState state = sm.AddState(newClip.name);
            state.motion = newClip;
            //设置默认状态
            if (state.name == "idle_Down")
            {
               sm.defaultState = state;
            }
            //_state.SetAnimationClip(newClip, _layer);
            //AnimatorStateTransition trans = sm.AddAnyStateTransition(_state);
            //trans.RemoveCondition(0);
        }

        AssetDatabase.SaveAssets();
        return animatorController;
    }

    /// 
    /// build八个方向动画
    /// 
    /// 
    /// 
    private static List BuildAnimationList(DirectoryInfo directories)
    {
        string _animationName = directories.Name;
        FileInfo[] _images = directories.GetFiles("*.png");
        //创建unit文件夹
        string _parentName = System.IO.Directory.GetParent(directories.FullName).Name;
        System.IO.Directory.CreateDirectory(m_animationPath + "/" + _parentName);

        Dictionary> _Dic = new Dictionary>();
        List _dicClips = new List();
        //创建方向文件夹
        for (int i = 1; i < 9; i++)
        {
            string _enumName = EnumToString((Orientation)i);
            System.IO.Directory.CreateDirectory(m_animationPath + "/" + _parentName + "/" + _enumName);
            _Dic.Add(i, new List());
        }


        for (int i = 0; i < _images.Length; i++)
        {
            //获取无扩展名的文件名
            string _fileName = Path.GetFileNameWithoutExtension(_images[i].ToString());
            int initial = (int)(_fileName[0]);
            //根据首字母添加
            // Debug.Log(_fileName[0]);
            // Debug.Log(initial);
            _Dic[initial - 48].Add(_images[i]);
        }

        foreach (int key in _Dic.Keys)
        {
            AnimationClip _clip = new AnimationClip();
            _clip = BuildAnimationClip(_Dic[key]);
            //动画循环
            if (_animationName.IndexOf("idle") >= 0)
            {
                //设置idle文件为循环动画
                SerializedObject serializedClip = new SerializedObject(_clip);
                AnimationClipSetting clipSettings = new AnimationClipSetting(serializedClip.FindProperty("m_AnimationClipSettings"));
                clipSettings.loopTime = true;
                serializedClip.ApplyModifiedProperties();
            }


            string _enumName = EnumToString((Orientation)key);
            System.IO.Directory.CreateDirectory(m_animationPath + "/" + _parentName + "/" + _enumName);
            AssetDatabase.CreateAsset(_clip, m_animationPath + "/" + _parentName
                + "/" + _enumName + "/" + _animationName + "_" + _enumName + ".anim");
            _dicClips.Add(_clip);
        }
        return _dicClips;
    }

    static string EnumToString(Orientation ori)
    {
        return Enum.GetName(typeof(Orientation), ori);
    }


    /// 
    /// Build动画
    /// 
    /// 
    /// 
    static AnimationClip BuildAnimationClip(List fi) {
        AnimationClip _clipTemp = new AnimationClip();
        _clipTemp.frameRate = 30;
        //AnimationUtility.SetAnimationType(_clipTemp, ModelImporterAnimationType.Generic);

        EditorCurveBinding _curveBinding = new EditorCurveBinding();
        _curveBinding.type = typeof(SpriteRenderer);
        _curveBinding.path = "";
        _curveBinding.propertyName = "m_Sprite";
        ObjectReferenceKeyframe[] _keyFrames = new ObjectReferenceKeyframe[fi.Count];
        float _frameTime = 1 / 10f;
        for (int i = 0; i < _keyFrames.Length; i++)
        {
            Sprite _sprite = AssetDatabase.LoadAssetAtPath(DataPathToAssetPath(fi[i].FullName));
            //过时 Resources.LoadAssetAtPath(DataPathToAssetPath(_images[i].FullName));
            _keyFrames[i] = new ObjectReferenceKeyframe();
            _keyFrames[i].time = _frameTime * i;
            _keyFrames[i].value = _sprite;
        }

        AnimationUtility.SetObjectReferenceCurve(_clipTemp, _curveBinding, _keyFrames);
        AssetDatabase.SaveAssets();
        return _clipTemp;
    }


    private static string DataPathToAssetPath(string path)
    {
        if (Application.platform == RuntimePlatform.WindowsEditor)
        {
            return path.Substring(path.IndexOf("Assets\\"));
        }
        else {
            return path.Substring(path.IndexOf("Assets/"));
        }
    }


    #endregion

    #region Unity回调
    #endregion

    #region 事件回调
    #endregion

    #region 帮助方法
    #endregion
}

class AnimationClipSetting
{
    private SerializedProperty m_Property;
    private SerializedProperty Get(string property)
    {
        return m_Property.FindPropertyRelative(property);
    }

    public AnimationClipSetting(SerializedProperty prop)
    {
        this.m_Property = prop;
    }

    public float startTime {
        get { return Get("m_StartTime").floatValue; }
        set { Get("m_StartTime").floatValue = value; }
    }

    public float OrientationOffsetY {
        get { return Get("m_OrientationOffsetY").floatValue; }
        set { Get("m_OrientationOffsetY").floatValue = value; }
    }

    public float level {
        get { return Get("m_Level").floatValue; }
        set { Get("m_Level").floatValue = value; }
    }

    public float cycleOffset {
        get { return Get("m_CycleOffset").floatValue; }
        set { Get("m_CycleOffset").floatValue = value; }
    }

    public bool loopTime
    {
        get { return Get("m_LoopTime").boolValue; }
        set { Get("m_LoopTime").boolValue = value; }
    }

    public bool loopBlend {
        get { return Get("m_LoopBlend").boolValue; }
        set { Get("m_LoopBlend").boolValue = value; }
    }

    public bool loopBlendOrientation {
        get { return Get("m_LoopBlendOrientation").boolValue; }
        set { Get("m_LoopBlendOrientation").boolValue = value; }
    }

    public bool loopBlendPositionY {
        get { return Get("m_LoopBlendPositionY").boolValue; }
        set { Get("m_LoopBlendPositionY").boolValue = value; }
    }

    public bool loopBlendPositionXZ {
        get { return Get("m_LoopBlendPositionXZ").boolValue; }
        set { Get("m_LoopBlendPositionXZ").boolValue = value; }
    }

    public bool keepOriginalOrientation
    {
        get { return Get("m_KeepOriginalOrientation").boolValue; }
        set { Get("m_KeepOriginalOrientation").boolValue = value; }
    }

    public bool keepOriginalPositionY {
        get { return Get("m_KeepOriginalPositionY").boolValue; }
        set { Get("m_KeepOriginalPositionY").boolValue = value; }
    }

    public bool keepOriginalPositionXZ {
        get { return Get("m_KeepOriginalPositionXZ").boolValue; }
        set { Get("m_KeepOriginalPositionXZ").boolValue = value; }
    }

    public bool heightFromFeet {
        get { return Get("m_HeightFromFeet").boolValue; }
        set { Get("m_HeightFromFeet").boolValue = value; }
    }

    public bool mirror {
        get { return Get("m_Mirror").boolValue; }
        set { Get("m_Mirror").boolValue = value; }
    }
}

 

 

这样做有个问题,每一次点击BuildAnimation都会重新加载所有资源,如果数据量大的话,更新会很不方便。

有以下修改:

    [MenuItem("Assets/BuildAnimation")]
    static void BuildAnimations()
    {
        //选中的文件夹,不包括子文件夹
        UnityEngine.Object[] filter = Selection.GetFiltered(typeof(UnityEngine.Object), SelectionMode.TopLevel);
        //路径中包含"Raw" 或者选中的是"Raw"
        if (!AssetDatabase.GetAssetPath(filter[0]).Contains("Raw") || Path.GetFileNameWithoutExtension(AssetDatabase.GetAssetPath(filter[0])) == "Raw")
        {
            Debug.LogError("没有选中对的文件夹");
            return;
        }
        DirectoryInfo[] filterInfo = new DirectoryInfo[filter.Length];
        for (int i = 0; i < filter.Length; i++)
        {
            filterInfo[i] = new DirectoryInfo(Application.dataPath.Substring(0,Application.dataPath.LastIndexOf("/")) + "/" + AssetDatabase.GetAssetPath(filter[i]));
        }

        foreach (DirectoryInfo directories in filterInfo)
        {
            List clips = new List();
            foreach (DirectoryInfo ActionList in directories.GetDirectories())
            {
                List clipList = BuildAnimationList(ActionList);
                foreach (AnimationClip clip in clipList)
                {
                    clips.Add(clip);
                }
            }
            AnimatorController controller = BuildAnimationController(clips, directories.Name);
            BuildPrefab(directories, controller);
        }
    }


这样写,只会Build选中的文件夹。

 

 

 

 

你可能感兴趣的:(Unity)