脚本自动化生成状态机
给角色调试动作,经常会用到状态机,那么一般来说如果就几个角色,那么用Unity的可视化状态机编辑就挺方便了,但是如果有几十个甚至上百个角色的模型,要生成状态机,一个一个调试,不知道要花费多少时间精力,幸好Unity提供了Editor的状态机API,供我们来处理批量的状态机。
首先得有一个模版的AnimatorController
用于处理大部分相同的状态,包括状态机以及状态之间的切换等等
然后拷贝一份到你的角色目录
if (!File.Exists(animatorControllerPath + fileName))
{
FileUtil.CopyFileOrDirectory(templetControlPath + fileName, animatorControllerPath + "/" + generateName);
Debug.Log("copy animator control success");
}
//注意刷新,否则导致animatorController为null
AssetDatabase.Refresh();
注意刷新下,不然生成的为空
获取角色目录下面所有的动画clip
string[] assets = AssetDatabase.FindAssets("t:GameObject", animPath.Split());
AnimationClip[] animClip = new AnimationClip[assets.Length];
//获得目录下所有的AnimationClip对象
for (int i = 0; i < assets.Length; ++i)
{
string path = AssetDatabase.GUIDToAssetPath(assets[i]);
animClip[i] = AssetDatabase.LoadAssetAtPath(path, typeof(AnimationClip)) as AnimationClip;
}
//如果一个fbx中有多个AnimationClip对象咋办呢?
var aniArray = AssetDatabase.LoadAllAssetsAtPath(path);
var filterArray = aniArray.Where(t => t.GetType() == typeof(AnimationClip) && !t.name.Contains("Take")).ToArray();
for (int j = 0; j < filterArray.Length; j++)
{
animClip[j] = filterArray[j] as AnimationClip;
}
多个AnimationClip,我的做法是获取所有的,然后过滤出来就OK了,可能会有更好的方法,如果有请留言哦!!
拿到AnimatorController里面的状态,然后按照你的规则,往状态里面添加Motion,也就是AnimationClip,就可以啦
for (int i = 0; i < sm.states.Length; ++i)
{
for (int j = 0; j < animClip.Length; ++j)
{
if (animClip[j].name.ToLower().Contains(sm.states[i].state.name.ToLower()))
{
sm.states[i].state.motion = animClip[j];
}
if (matchMap.ContainsKey(sm.states[i].state.name))
{
if (animClip[j].name.Contains(matchMap[sm.states[i].state.name]))
sm.states[i].state.motion = animClip[j];
}
}
}
可能有的状态是BleedTree
BlendTree runIdleBlendTree = new BlendTree();
runIdleBlendTree.name = "BlendTree";
runIdleBlendTree.AddChild(idle);
runIdleBlendTree.AddChild(run);
runIdleBlendTree.blendParameter = "Speed";
sm.states[i].state.motion = runIdleBlendTree;
需要生成状态,然后再添加AnimationClip
for (int i = 0; i < actionClipList.Count; i++)
{
var action = sm.AddState(actionClipList[i].name, new Vector3(600, 300 + 60 * i));
var tran = dashState.AddTransition(action);
tran.exitTime = 1;
tran.duration = 0;
tran.offset = 0;
tran.AddCondition(AnimatorConditionMode.Equals, 5 + i, "CMD");
action.AddTransition(jumpbackState);
}
补充一下 如果修改Project目录下面的资源可以直接调用
AssetDatabase.RenameAsset(path, newName);