unity 动画状态机重复利用
在unity 项目工程里,常有几十个NPC,几十个小怪的动画状态机都是相同的,类似于这个情况,可以只需要制作一套状态机,复制到每个动画的文件夹里面,然后就是拉入动画了。
这个的前提就是每个动画里面都是相同的,大家的状态机都是一样的。
下面的工具就是方便来导入动画的,是相应的动画状态机保持着相应的动画。
代码和介绍
[MenuItem("Assets/替换为当前文件夹的动画")]
public static void ReplaceAnimatorClips()
{
Object animObj = Selection.activeObject;
AnimatorController animator = animObj as AnimatorController;
string folderpath = Path.GetDirectoryName(AssetDatabase.GetAssetPath(animObj));
GetAllFiles(folderpath);
if (files.Count <= 0) return;
animationClips.Clear();
for (int i = 0; i < files.Count; i++)
{
string name = Path.GetFileNameWithoutExtension(files[i]);
string[] names = name.Split('@');
if (names.Length == 2)
{
string clipname = names[1];
animationClips[clipname.ToLower()] = files[i];
}
}
ChildAnimatorState[] childstates = animator.layers[0].stateMachine.states;
foreach (var childstate in childstates)
{
AnimatorState state = childstate.state;
Motion mo = state.motion;
if (mo == null)
{
Debug.LogError(state.name + "节点动作是空");
continue;
}
if (mo.GetType().Equals(typeof(BlendTree)))
{
BlendTree tree = (BlendTree)mo;
ReplaceMotionInLocalFolder(tree);
}
else
{
ReplaceMotionInLocalFolder(state);
}
}
AssetDatabase.SaveAssets();
}
[MenuItem(“Assets/替换为当前文件夹的动画”)]
这句代码我们选中所需要的状态机就可以鼠标右键来快捷方式调用这个方法了。
在判断动画状态机里面不为空的时候,就可以去改变里面的动画片段了。
在这里我们分为两种,一种是普通动画,一种是BlendTree。
if (mo.GetType().Equals(typeof(BlendTree)))
{
BlendTree tree = (BlendTree)mo;
//取代BlendTree里面的动画
ReplaceMotionInLocalFolder(tree);
}
else
{
//取代普通的动画
ReplaceMotionInLocalFolder(state);
}
普通的动画
public static void ReplaceMotionInLocalFolder(AnimatorState state)
{
string name = state.motion.name;
if (GetLocalMotionFile(name) != null)
{
state.motion = GetLocalMotionFile(name);
}
}
这里是更换普通的动画片段,只需要把普通的名字传进去,更换一下就是可以的了。
同时看下 GetLocalMotionFile 函数
//animationClips 为动画片段
static Dictionary<string, string> animationClips = new Dictionary<string, string>();
public static Motion GetLocalMotionFile(string name)
{
if (animationClips.ContainsKey(name.ToLower()))
{
AnimationClip mo = AssetDatabase.LoadAssetAtPath(animationClips[name.ToLower()], typeof(AnimationClip)) as AnimationClip;
if (mo != null)
{
return mo;
}
else
{
Debug.LogWarning("no this name clip in this folder" + name);
}
}
else
{
Debug.LogWarning("no this name clip in this folder" + name);
}
return null;
}