【Unity技巧4】使用代码给动画状态机批量连线
前段时间写技能编辑器的时候, 发现很多的动画片段需要连线,手动连线肯定是很麻烦。
那么如何优雅得连线呢?
那就是使用AnimatorStateMachine的API来完成这些事件。
核心API
AnimatorStateMachine.AddTransition //连线
AnimatorStateMachine.AddExitTransition //连线到退出
AnimatorStateMachine.RemoveEntryTransition //移除连线
AnimatorState.AddState //添加动画片段到状态机

编辑器代码:
public static class XiaocaoEditorAnimTool
{
//添加一个Clip到动画机
public static bool AddClipToAnimator(AnimatorController ac, AnimationClip item)
{
if (!ac.animationClips.Contains(item))
{
AnimatorStateMachine sm = ac.layers[0].stateMachine;
AnimatorState state = sm.AddState(item.name, sm.exitPosition + Vector3.up * Random.Range(100, 800));
state.motion = item;
state.AddExitTransition(true);
Debug.Log($"anim add {item.name}");
EditorUtility.SetDirty(ac);
return true;
}
else
{
Debug.Log($"yns has {item.name}");
return false;
}
}
[MenuItem("Assets/AnimatorTool/移除所有连线")]
public static void RemoveAllTransmiss()
{
OnRemoveAllTransmiss(Selection.activeObject as AnimatorController);
}
[MenuItem("Assets/AnimatorTool/自动连线")]
public static void SetIdleTransmiss()
{
RemoveAllTransmiss();
OnSetIdleTransmiss(Selection.activeObject as AnimatorController);
}
public static void OnSetIdleTransmiss(AnimatorController ac)
{
foreach (var item in ac.layers[0].stateMachine.states)
{
if (item.state.name.ToLower() != "idle")
{
item.state.AddExitTransition(true);
}
}
}
public static void OnRemoveAllTransmiss(AnimatorController ac, List<string> unRemoves = null)
{
var stateMachine = ac.layers[0].stateMachine;
foreach (var item in stateMachine.entryTransitions)
{
if (unRemoves != null)
{
if (unRemoves.Contains(item.destinationState.name))
{
continue;
}
}
Debug.Log("yns remove " + item.destinationState);
stateMachine.RemoveEntryTransition(item);
}
foreach (var item in stateMachine.anyStateTransitions)
{
Debug.Log("yns remove " + item.destinationState);
stateMachine.RemoveAnyStateTransition(item);
}
//foreach (var item in ac.layers[0].stateMachine.stateMachines)
//{
// //Debug.Log("yns stateMachines " + item.stateMachine.ToString());
//}
foreach (var item in ac.layers[0].stateMachine.states)
{
if (unRemoves != null)
{
if (unRemoves.Contains(item.state.name))
{
continue;
}
}
Debug.Log("yns states " + item.state.ToString());
foreach (var tr in item.state.transitions)
{
item.state.RemoveTransition(tr);
}
}
EditorUtility.SetDirty(ac);
AssetDatabase.SaveAssets();
}
}