您的位置:首页 > 移动开发 > Unity3D

unity3d自动生成2D动画

2015-02-05 22:57 246 查看
关于自动生成动画,雨松MOMO有一篇比较完整的文章了,链接在此 点击打开链接

生成AnimationClip、Controller以及设置State等都是参考了他提供的代码,这里我主要补充一下如何给2d texture设置锚点。

这里主要看代码吧,值得一提的是,设置自定义锚点必须将spriteAlignment设置为9(customer),否则设置的pivot将不起作用。

[MenuItem("JyGame/BuildClip")]
    static void BuildClip()
    {
        //AnimationXml xml = ResourceManager.Get
        ResourceManager.Init();
        List<string> actionList = new List<string>();

        foreach(var d in TargetDir.GetDirectories())
        {
            string animationName = d.Name;
            Debug.Log("building " + animationName);
            if (ResourceManager.Get<JyGame.AnimationNode>(animationName) == null)
            {
                Debug.LogWarning("错误, 找不到xml中锚点描述!" + animationName);
                continue;
            }

            //调整锚点
            foreach(var f in new DirectoryInfo(d.FullName + "\\rawdata").GetFiles("*.png"))
            {
                string[] paras = f.Name.Replace(".png","").Split('-');
                string animation = paras[0];
                string action = paras[1];
                int count = int.Parse(paras[2]);

                AnimationImage img = null;
                try
                {
                    img = ResourceManager.Get<JyGame.AnimationNode>(animation).GetGroup(action).images[count];
                }
                catch
                {
                    Debug.Log("找不到文件对应的描述,删除" + f.FullName);
                    File.Delete(f.FullName);
                    continue;
                }
                string path = DataPathToAssetPath(f.FullName);
                TextureImporter textureImporter = AssetImporter.GetAtPath(path) as TextureImporter;
                TextureImporterSettings tis = new TextureImporterSettings();
                textureImporter.ReadTextureSettings(tis);

                tis.spriteAlignment = 9; //customer
                tis.spritePixelsPerUnit = 1;
                tis.mipmapEnabled = false;
                tis.spritePivot = new Vector2((float)img.anchorx / img.w, (float)(img.h - img.anchory) / img.h);

                textureImporter.SetTextureSettings(tis);
                if(!actionList.Contains(action))
                {
                    actionList.Add(action);
                }
                AssetDatabase.ImportAsset(path);
            }

            List<AnimationClip> clips = new List<AnimationClip>();
            //创建clip
            foreach(var action in actionList)
            {
                FileInfo[] images = new DirectoryInfo(d.FullName + "\\rawdata").GetFiles(string.Format("*-{0}-*.png",action));
                AnimationClip clip = new AnimationClip();
                AnimationUtility.SetAnimationType(clip, ModelImporterAnimationType.Generic);
                EditorCurveBinding curveBinding = new EditorCurveBinding();
                curveBinding.type = typeof(SpriteRenderer);
                curveBinding.path = "";
                curveBinding.propertyName = "m_Sprite";
                ObjectReferenceKeyframe[] keyFrames = new ObjectReferenceKeyframe[images.Length];
                float frameTime = 1 / 10f;
                if(action == "stand")
                {
                    frameTime = 1 / 4f;
                }
                for (int i = 0; i < images.Length; i++)
                {
                    Sprite sprite = Resources.LoadAssetAtPath<Sprite>(DataPathToAssetPath(images[i].FullName));
                    keyFrames[i] = new ObjectReferenceKeyframe();
                    keyFrames[i].time = frameTime * i;
                    keyFrames[i].value = sprite;
                }
                
                clip.frameRate = 10;
                if (action == "stand") clip.frameRate = 4;

                if (action != "attack")
                {
                    //设置idle文件为循环动画
                    SerializedObject serializedClip = new SerializedObject(clip);
                    AnimationClipSettings clipSettings = new AnimationClipSettings(serializedClip.FindProperty("m_AnimationClipSettings"));
                    clipSettings.loopTime = true;
                    serializedClip.ApplyModifiedProperties();
                }
  
                AnimationUtility.SetObjectReferenceCurve(clip, curveBinding, keyFrames);
                AssetDatabase.CreateAsset(clip, TARGET_DIR + animationName + "\\" + action + ".anim");
                clips.Add(clip);
                AssetDatabase.SaveAssets();
            }

            //创建controller
            AnimatorController animatorController =
                AnimatorController.CreateAnimatorControllerAtPath(TARGET_DIR + animationName + "\\controller.controller");
            AnimatorControllerLayer layer = animatorController.GetLayer(0);
            UnityEditorInternal.StateMachine sm = layer.stateMachine;
            //animatorController.AddParameter("attack", AnimatorControllerParameterType.Trigger);
            //animatorController.AddParameter("move", AnimatorControllerParameterType.Trigger);
            //animatorController.AddParameter("stand", AnimatorControllerParameterType.Trigger);

            State standState = null;
            State attackState = null;
            State moveState = null;
            foreach (AnimationClip newClip in clips)
            {
                
                State state = sm.AddState(newClip.name);
                state.SetAnimationClip(newClip, layer);
                if (newClip.name == "stand")
                {
                    sm.defaultState = state;
                    standState = state;
                }else if(newClip.name =="move")
                {
                    moveState = state;
                }else if(newClip.name == "attack")
                {
                    attackState = state;
                }
                Transition trans = sm.AddAnyStateTransition(state);
                trans.RemoveCondition(0);
            }
            if(attackState != null && standState!=null)
            {
                var trans = sm.AddTransition(attackState, standState);
                //var condition = trans.AddCondition();
                //condition.mode = TransitionConditionMode.ExitTime;
            }
            AssetDatabase.SaveAssets();

            //生成Prefab 添加一张预览用的Sprite
            FileInfo tagImage = new DirectoryInfo(d.FullName + "\\rawdata").GetFiles("*.png")[0];
            GameObject go = new GameObject();
            go.name = animationName;
            SpriteRenderer spriteRender = go.AddComponent<SpriteRenderer>();
            spriteRender.sprite = Resources.LoadAssetAtPath<Sprite>(DataPathToAssetPath(tagImage.FullName));
            Animator animator = go.AddComponent<Animator>();
            animator.runtimeAnimatorController = animatorController;
            PrefabUtility.CreatePrefab(TARGET_DIR + animationName + "/sprite.prefab", go);
            DestroyImmediate(go);
        }
    }

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

    class AnimationClipSettings
    {
        SerializedProperty m_Property;

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

        public AnimationClipSettings(SerializedProperty prop) { m_Property = prop; }

        public float startTime { get { return Get("m_StartTime").floatValue; } set { Get("m_StartTime").floatValue = value; } }
        public float stopTime { get { return Get("m_StopTime").floatValue; } set { Get("m_StopTime").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; } }
    }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: