Hi guys. I am writing an editor script, I am getting value from animator and retrieve all parameters and convert them in enum. Everything is working fine except to one major bug.
this code runs in OnEnable of my editor script
AnimatorControllerParameter[] parameters = scriptTarget.Animations.animator.parameters;
animatorParameters = new string[scriptTarget.Animations.animator.parameterCount];
selectedParameter = new int[scriptTarget.Animations.animator.parameterCount];
for (int x = 0; x < parameters.Length; x++)
{
animatorParameters[x] = parameters[x].name;
}
this code gives me all parameters and cache in array. Looks Good.
then I convert that in enum.
Animator Controllers aren’t designed to be accessed in Edit Mode so there are some things you just won’t be able to do. Try using animator.runtimeAnimatorController as UnityEditor.AnimatorController; which might give you access to what you need.
@Kybernetik seem to just point out a clue but not how to utilize UnityEditor.Animations.AnimatorController in any manner, so I will complete his answer. Besides its not really a bug since it can be resolved via UnityEditor.Animations.AnimatorController.
Let me give a brief outlook of what the issue is:
Reading UnityEngine.Animator.parameters after a parameter is added/removed via the Animator window will result in an empty array. The array will refresh after a scene is loaded or after scripts are compiled. I suspect this is due to how some UnityEngine scripts do not necessarily update in realtime in Editor Mode.
Solution:
In order to get the refreshed parameters in realtime and in Editor Mode after adding/removing a parameter via the Animator window, you will need to load the AnimatorController asset (asset with .controller extension) using AssetDatabase.LoadAssetAtPath().
Since you have the controller reference from Animator.runtimeAnimatorController (type RuntimeAnimatorController), then it a matter of finding its path and loading it as a UnityEditor.Animations.AnimatorController using AssetDatabase.GetAssetPath().
So it will look like this: AnimatorController editorController = (AnimatorController)AssetDatabase.LoadAssetAtPath(AssetDatabase.GetAssetPath([your Animator reference].runtimeAnimatorController), typeof(AnimatorController));
After that you can access the parameters using editorController.parameters and the array values in it will refresh each time there is a change in the Animator parameters.
Apologies for necro-ing the thread but just wanted to add some useful further info to @altan86 's answer. I was writing a script for a custom editor for setting any float parameter for an attached animator, but was having trouble getting changes to save - which led me here.
Some of the game objects I am targeting with this script use Animator Override Controllers rather than Animator Controllers, which meant there were a few extra steps to getting altan’s method to work.
// get animator component
animatorComponent = script.gameObject.GetComponent<Animator>();
// get the runtime animator controller
RuntimeAnimatorController runtimeController = animatorComponent.runtimeAnimatorController;
// if it is an override controller we need to get the base controller
if (runtimeController.GetType() == typeof(AnimatorOverrideController))
{
AnimatorOverrideController overrideController = (AnimatorOverrideController)runtimeController;
// runtimeAnimatorController of an AnimatorOverrideController is the base controller
runtimeController = overrideController.runtimeAnimatorController;
}
// load the .controller file as a UnityEditor.Animations.AnimatorController
// this allows for updating of floatParamNames in Edit Mode
AnimatorController editorController =
(AnimatorController)AssetDatabase.LoadAssetAtPath(AssetDatabase.GetAssetPath(runtimeController), typeof(AnimatorController));
Basically it’s just a check on the Type of the runtime animation controller once you get it from the Animator component. Not too complicated but took some searching to find the solution, may save someone some time!