I have a base AnimatorController and an AnimatorOverrideController.
Things work well except for when I swap out the override AnimationClip from the list of AnimationClipPairs at runtime! It resets the animator controller
That is all I have written for the swap and it results in the entire animator being reset. It goes back to its default state and all parameters are reset.
Is there a way that I can somehow safely swap the clip and keep the current state I am in as well as the parameters? (The state I am in is not the state that I want to swap the clip for)
It’s expected that the animator is resetted when you change a clip. This is something we would like to change in the future.
In the meantime you need to save the Animator State before changing the clip, change the clip and then push back the saved state.
Animator animator = GetComponent<Animator>();
AnimatorStateInfo[] layerInfo = new AnimatorStateInfo[animator.layerCount];
for (int i = 0; i < animator.layerCount; i++)
{
layerInfo[i] = animator.GetCurrentAnimatorStateInfo(i);
}
// Do swap clip in override controller here
// Push back state
for (int i = 0; i < animator.layerCount; i++)
{
animator.Play(layerInfo[i].nameHash, i, layerInfo[i].normalizedTime);
}
// Force an update
animator.Update(0.0f);
However that still doesn’t solve my issue with the actual parameters changing. I have a float value that I need to stay the same during the clip change. Is there any similar solution to this?
As far as I can see there is no way of getting a list of these parameters which makes that solution not entirely ideal. I can’t rely on knowing the names of the parameters that I want to save because this is a very generic operation I am doing.
Thanks to your initial post and some reworking of my controller I was able to get what I wanted without making use of parameters so thanks for that!
I’m using Mechanim.Dev’s solution ( as well as manually resetting some of my basic controller bools) but I’m now getting this error in the console:
Calling Animator.GotoState on Synchronize layer
This appears to be happening when I call animator.Play() in the ‘push back state’ block in the example code, and the effect is that my replacement clips don’t play.
Could this be due to the fact that I’m calling this inside a coroutine?
Also, I just wanted to clarify how Unity 5 will improve this. Will Unity 5 eliminate the need for us to manually save/restore the state, or will it only make it easier for us to save/restore the state ourselves?
Hi,
I’ve been trying this on a simple test in 5.1.1 and it doesn’t seem to work anymore (or I’m doing something wrong). After saving the states and changing the clips through the override controller, the original Animator becomes corrupt it seems, reporting 0 layers and 0 parameters. No error is raised and the clip replacement works, but the states are not restored correctly and so the FSM resets.
Hi Ben_SEM,
i think i found the solution to your problem with the resetting FSM:
Animator animator = GetComponent<Animator>();
AnimatorStateInfo[] layerInfo = new AnimatorStateInfo[animator.layerCount];
for (int i = 0; i < animator.layerCount; i++)
{
layerInfo[i] = animator.GetCurrentAnimatorStateInfo(i);
}
// Do swap clip in override controller here
// Force an update
animator.Update(0.0f);
// Push back state
for (int i = 0; i < animator.layerCount; i++)
{
animator.Play(layerInfo[i].nameHash, i, layerInfo[i].normalizedTime);
}
As you can see, i moved the animator.Update(0.0f) line right before the // Push back state and it seems to work just fine for me.
Two more things to know if you’re trying to pull this one:
1- spinning the animator again (though animator.Update(0f)) after restoring the animator state prevents some cases of one-frame undetermined state
2 - backing up and restoring the animator parameters as well is a good idea. See Parameters and States of Animator Reset on Object's Disable - Questions & Answers - Unity Discussions. Note that I don’t know of any way to save and restore the trigger parameters, which due to the way we build our animators is not an issue for us; but that may be a blocking point for others.
[Edit: more points!]
3 - restoring the state of the animator does not restore transitions (blends) that were in progress. Haven’t found a way to do that properly, though maybe using CrossFade could help.
Animator.layercount returns 0 for me when I use an animator controller override in 2020.2.2f1, and it also says animator doesnt have an animator controller when it clearly does
Either post a thread about it and give some actual details or report a bug in Unity via the Help menu. Don’t necro a 6 year old thread just because it’s tangentially related.