unity3d自动生成2D动画

关于自动生成动画,雨松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; } }
    }


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Unity Puppet3D是一个基于Unity引擎的工具,用于创建和控制2D角色。它使用了骨骼动画系统和绑定技术,使开发者能够更轻松地制作高质量的角色动画。 Unity Puppet3D提供了一个直观的界面,可以轻松创建角色的骨骼结构。通过一系列的连接、父子关系和绑定操作,可以将各个部位连接起来,形成一个完整的角色模型。开发者可以根据实际需求调整关节的位置、角度和大小,使角色具有多种表现形式。 除了创建骨骼结构外,Unity Puppet3D还支持角色动画的控制。它提供了一组内置的动画控制器和状态机,开发者可以使用这些工具来设计和编辑角色的动作。通过基于关键帧的动画系统,可实现角色在不同动作之间的平滑过渡和衔接。 Unity Puppet3D还支持插值技术,可以在不同的关键帧之间生成平滑的过渡帧。这使得角色动画更加流畅,并且可以通过调整插值参数来控制动画的速度和运动方式。 此外,Unity Puppet3D还提供了一些额外的功能,如蒙皮和材质编辑,开发者可以使用这些功能来增强角色的外观和效果。 总而言之,Unity Puppet3D是一个强大的工具,可以帮助开发者轻松制作和控制2D角色动画。它提供了丰富的功能和直观的界面,使开发者能够快速创建出高质量的角色模型和动画效果。无论是游戏开发还是动画制作,Unity Puppet3D都是一个值得尝试的工具。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值