Reputation: 26429
I'd like to write an editor menu item that accesses currently open animation controller and destroys/creates/modifies animation transitions.
Basically, I need to iterate through all animation states/clips in currently open animator controller, and based on their names create transitions with specific and adjust playback speed for all clips.
I have this code snippet:
UnityEditorInternal.AnimatorController ac = GetComponent<Animator>().runtimeAnimatorController as UnityEditorInternal.AnimatorController;
int numLayers = ac.layerCount;
for(int i = 0; i<numLayers; i++){
UnityEditorInternal.AnimatorControllerLayer layer = ac.GetLayer(i);
Debug.Log ("Layer " + i + " is: " + layer.name + " and has " + layer.stateMachine.stateCount + " states");
UnityEditorInternal.StateMachine sm = layer.stateMachine;
for(int n = 0; n<sm.stateCount; n++){
UnityEditorInternal.State state = sm.GetState(n);
Debug.Log ("State " + state.name + " is " + state.GetHashCode());
UnityEditorInternal.Transition[] list = sm.GetTransitionsFromState(state);
for(int j = 0; j<list.Length; j++){
UnityEditorInternal.Transition transition = list[j];
Debug.Log ("Transition: " + transition.name + " is " + transition.GetHashCode());
}
}
}
However, it does not compile on Unity5 (written for Unity 4, most likely), and I'm unsure how to get a hold of currently open AnimatorController using Unity 5 functions.
The animator controller class seems to be defined as UnityEditor.Animations.AnimatorController
, but I can't figure out how to grab currently open one.
Any advice?
Upvotes: 1
Views: 11567
Reputation: 1515
Slightly hacky way to get to reflectively get current AnimatorController in open Animator window (it should be focused):
static AnimatorController GetCurrentController()
{
AnimatorController controller = null;
var tool = EditorWindow.focusedWindow;
var toolType = tool.GetType();
var controllerProperty = toolType.GetProperty("animatorController", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
if (controllerProperty != null)
{
controller = controllerProperty.GetValue(tool, null) as AnimatorController;
}
else
{
Debug.Log("EditorWindow.focusedWindow " + tool + " does not contain animatorController",tool);
}
return controller;
}
Works as of my current Unity version (5.2.2p4).
Then I was combining that with using the Selection.objects to find selected states to make my tools with it.
Upvotes: 0
Reputation: 12608
Thanks to your answer i came up with the following:
Animator animator = GetComponent<Animator>();
string assetPath = AssetDatabase.GetAssetPath(animator.runtimeAnimatorController);
AnimatorController controller = AssetDatabase.LoadAssetAtPath<AnimatorController>(assetPath);
This works for me!
Upvotes: 3
Reputation: 26429
I've managed to access AnimatorController via inspector context menu. That's not very convenient (because to process the whole controller, I need to select it in project view first), but it works.
public class AnimImportTools: MonoBehaviour{
//.....
[MenuItem("CONTEXT/AnimatorController/Make transitions immediate")]
private static void makeTransitionsImmediate(){
UnityEditor.Animations.AnimatorController ac = Selection.activeObject as UnityEditor.Animations.AnimatorController;
foreach(var layer in ac.layers){
foreach(var curState in layer.stateMachine.states){
foreach(var transition in curState.state.transitions){
transition.duration = 0.0f;
transition.exitTime = 1.0f;
}
}
}
}
//.....
}
If someone knows better way to do it - i.e. add menu in more accessible location OR run this script from main menu (and get currently open animatorcontroller from there), I'm all ears.
Upvotes: 3