さけのさかなのブログ

同人ゲーム開発やってます。Unity使ったりする。

ScriptableObjectからAnimationClip作成

 前回言ってた、フレームアニメーションの作成スクリプト。
 (フレームアニメーションはいわゆるパタパタマンガのことを指してる……でいいと思う)

 最終的にはAnimatorControllerが一発で作成できればいいなあ、と考えているのだけど、どこまで機能を持たせるべきか決めるのがタイヘンなのと、どうやらかなり黒魔術じみたことをしなきゃいけないらしいぞ、てなわけで、まだそこまでやらない。やるかどうかも分からない。
 今回はAnimationClipの作成までを行う。

 まずはScriptableObjectの定義。

    using UnityEngine;
    using System.Collections;

    public class FrameAnimation : ScriptableObject
    {
        [System.Serializable]
        public class Frame
        {
            public float time;
            public Sprite sprite;
        }

        public Frame[] frames;
    }

 そしてインスペクタ拡張で、アニメーション作成機能をつける。

    using System.IO;
    using UnityEditor;
    using UnityEngine;

    [CustomEditor(typeof(FrameAnimation))]
    public class FrameAnimationEditor : Editor
    {
        public override void OnInspectorGUI()
        {
            DrawDefaultInspector();
            if (GUILayout.Button("Create Animation"))
            {
                var frameAnimation = (FrameAnimation)target;
                string path = GenerateUniqueAssetPath(frameAnimation, "anim");

                var obj = CreateAnimationClip(frameAnimation);

                obj.name = frameAnimation.name;
                AssetDatabase.CreateAsset(obj, path);
                EditorUtility.SetDirty(obj);
            }
        }

        static public string GenerateUniqueAssetPath(Object selectedObject, string extension)
        {
            string objectName = selectedObject.name;
            string dirPath = Path.GetDirectoryName(AssetDatabase.GetAssetPath(selectedObject));
            string path = string.Format("{0}/{1}." + extension, dirPath, objectName);
            return AssetDatabase.GenerateUniqueAssetPath(path);
        }

        public static AnimationClip CreateAnimationClip(FrameAnimation frameAnimation)
        {
            AnimationClip animClip = new AnimationClip();

            EditorCurveBinding curveBinding = new EditorCurveBinding();
            curveBinding.type = typeof(SpriteRenderer);
            curveBinding.path = "";
            curveBinding.propertyName = "m_Sprite";

            ObjectReferenceKeyframe[] keyFrames = new ObjectReferenceKeyframe[frameAnimation.frames.Length];

            for (int i = 0; i < frameAnimation.frames.Length; i++)
            {
                keyFrames[i] = new ObjectReferenceKeyframe();
                keyFrames[i].time = frameAnimation.frames[i].time;
                keyFrames[i].value = frameAnimation.frames[i].sprite;
            }

            AnimationUtility.SetAnimationType(animClip, ModelImporterAnimationType.Generic);
            AnimationUtility.SetObjectReferenceCurve(animClip, curveBinding, keyFrames);

            return animClip;
        }
    }

 ちなみに、だいたいここに書いてある。