这个是我现在所知最正确的MecAnim的用法了。先上代码:
using UnityEngine; using UnityEditor; using UnityEditorInternal; using System; using System.Collections; using System.Collections.Generic; public class GetAnimationClips : AssetPostprocessor { void OnPostprocessModel(GameObject go) { List<AnimationClip> clips = new List<AnimationClip>(); UnityEngine.Object[] objects = AssetDatabase.LoadAllAssetsAtPath(assetPath); Debug.Log(objects.Length); foreach (var obj in objects) { AnimationClip clip = obj as AnimationClip; if (clip != null && clip.name.IndexOf("__preview__") == -1) { clips.Add(clip); } } CreateAnimationController(assetPath, clips); } static void CreateAnimationController(string path, List<AnimationClip> clips) { path = path.Replace("\\", "/").Replace(".FBX", ".fbx"); string acPath = path.Replace(".fbx", ".controller"); string prefabPath = path.Replace(".fbx", ".prefab"); // 创建动画控制器 AnimatorController animatorController = AnimatorController.CreateAnimatorControllerAtPath(acPath); AnimatorControllerLayer layer = animatorController.GetLayer(0); UnityEditorInternal.StateMachine sm = layer.stateMachine; Vector3 anyStatePosition = sm.anyStatePosition; float OFFSET_X = 220; float OFFSET_Y = 60; float ITEM_PER_LINE = 4; float originX = anyStatePosition.x - OFFSET_X * (ITEM_PER_LINE / 2.5f); float originY = anyStatePosition.y + OFFSET_Y; float x = originX; float y = originY; foreach (AnimationClip newClip in clips) { State state = sm.AddState(newClip.name.ToLower()); state.SetAnimationClip(newClip, layer); state.position = new Vector3(x, y, 0); x += OFFSET_X; if (x >= originX + OFFSET_X * ITEM_PER_LINE) { x = originX; y += OFFSET_Y; } } // 创建prefab string name = path.Substring(path.LastIndexOf("/") + 1).Replace(".fbx", ""); prefabPath = "Assets/Resources/" + name + ".prefab"; GameObject go = AssetDatabase.LoadAssetAtPath(path, typeof(GameObject)) as GameObject; go.name = name; Animator animator = go.GetComponent<Animator>(); if (animator == null) { animator = go.AddComponent<Animator>(); } animator.applyRootMotion = false; animator.runtimeAnimatorController = animatorController; //AssetDatabase.CreateAsset(go, prefabPath); PrefabUtility.CreatePrefab(prefabPath, go); GameObject.DestroyImmediate(go, true); AssetDatabase.SaveAssets(); } }
1、AssetDatabase.LoadAllAssetsAtPath通过这个函数可以加载fbx文件(包含所有动画信息)。这个是根据fbx文件获取AnimationClip的方法。
2、AssetPostprocessor这个是Unity资源加载的接口。自动生成动画控制器的代码可以不放在这里,可以扩展Menu菜单完成对应功能(如遍历选择文件夹下的fbx文件并进行相关处理)。
这个是我现在所知的MMO中最正确的MecAnim的用法:
1、不要手工编辑.controller文件,无论是加载动画还是连线,在MMO中动画量相当庞大,人工编辑这些绝对是无法让人接受的。
2、MecAnim有一定优势,如重定向,现在几乎所有的MMO都是用的老的动画系统。不过我认为,我的这个方法可以兼容老的动画系统和新的动画系统,或者说,可以使老的动画系统的项目平滑过渡到新的动画系统
3、我们维护动画的方式可能是这样的,美术给出模型,如果可能的话,最好切分好动画(貌似maya是支持的,blender也是支持的,但是3dmax未知,比如我使用blender导出火炬之光的模型到unity中,unity可以直接识别出切分好的动画,而不需要手动切动画)。如果没有的话,就需要一个配置文件(比如excel)维护好动画的起始、结束帧的信息。在导入模型的时候,可以根据这个配置文件通过代码添加AnimationClip。
4、自动生成AnimatorController的思路一样可以应用到老的动画系统,因为其最核心的内容就是如何通过fbx获取到AnimationClip信息。如果是老的动画系统就是把AnimationClip添加到prefab的Animation的动画列表中。
5、我是如何使用新的动画系统的:
GameObject prefab = Resources.Load("player") as GameObject; GameObject go = Instantiate(prefab) as GameObject; Animator animator = go.GetComponent<Animator>(); animator.CrossFade("idle", 0.25f, 0);
原文:http://blog.csdn.net/langresser_king/article/details/43878113