I just upgraded to 5.4. I am having some problems with my animation override controller code. In 5.3, I was able to do manual animation controller overrides with this code:
/// <summary>
/// Sub in real animations for stubs
/// </summary>
/// <param name="animator">Reference to animator</param>
public void SetCurrentAnimation(Animator animator, string prevAttack)
{
RuntimeAnimatorController myController = animator.runtimeAnimatorController;
AnimatorOverrideController animatorOverride = new AnimatorOverrideController();
animatorOverride.runtimeAnimatorController = myController;
animatorOverride[prevAttack] = animClip;
animator.runtimeAnimatorController = animatorOverride;
}
I have an override controller attached to the object because some animations use the above method and some use mechanim ui. Right after upgrading, I now get this:
line 7:
Cannot nest AnimatorOverrideController 'Player' with ''.
UnityEngine.AnimatorOverrideController:set_runtimeAnimatorController(RuntimeAnimatorController)
line 9:
Could not set Runtime Animator Controller. The controller is an AnimatorOverrideController with no AnimatorController to override.
UnityEngine.Animator:set_runtimeAnimatorController(RuntimeAnimatorController)
yes this is still supported, but you cannot nest anymore AnimatorOverrideController. We had a few performance bug when users were deeply nesting OverrideController like you did but werenât aware.
So my guess is that when you call RuntimeAnimatorController myController = animator.runtimeAnimatorController;
there is already a AnimatorOverrideController in animator.runtimeAnimatorController.
You need to support this case like this
Unfortunately that change doesnât solve my problem. The exceptions are gone, but the animations are not subbed in. I donât know if it makes a difference, but that was how I was injecting animation clips that were not in mechanim. Is there a better way to do that?
Edit:
Rolling back to 5.3.6 to keep productive. I kept the same change as above, and even then the animations are not subbed beyond the very first one
Iâm still really confused. The sample you posted casts the runtime animator controller to an override controller and then assigns is to the same controller that is overwritten. Does that RuntimeAnimtorController property differ from the AnimatorOverrideController one?
Even if this is the case, the animations are not overriding. This is preventing us from upgrading to 5.4. Is there a bug in your sample or am I doing something wrong?
So I did take a look at your case
Here an updated version of your script with a workaround
Like I said you were nesting your controller which is not supported anymore for performance reason.
on the first frame that you press either 1,2 or 3 you are creating a new overridecontroller which you set in
animator.runtimeAnimatorController, and then on the next frame that you press 1,2 or 3 you fetch the same overridecontroler from animator.runtimeAnimatorController and override it with another override.
After a few thousand frame if the user did switch a lot from walk to run to jump you endup with a many nested override which can cause performance regression because of this nesting
You absolutly need to get the orignal controller and create a new override from this controller, so either keep a reference to the orignal controller in your script or fetch it like I did.
We would like to fix this issue in 5.4. You shouldnât need to recreate a new override each time you should be able to reuse the same one and only swap the clip that you want.
Yeah, it a little bit confusing I agree, GetCurrentAnimatorStateInfo(0).IsName(âMoveâ) work with State name but the override controller work with animation clip name.
Like I said there is a few hiccup with the overidecontroller but we are a looking at this to fix all of them for 5.4
Any more news on swapping animation clips on the AnimatorOverrideController? Is it possible to do without resetting the Animator state machine (active state, paramaters etc)?
Animation: Added AnimatorOverrideController.GetOverrides and AnimatorOverrideController.ApplyOverrides.
If you are using AnimatorOverrideController.clips I would suggest you to update your script to the new API GetOverrides/ApplyOverrides as it allocation free and ApplyOverrides send only one notification to the animator, the old API .clips was sending one notification for each changed clips.
Iâve been having issues with animation overriding for some time when trying to switch to Unityâs most recent versions (was using 5.3.4 up until now, where those nested overrides were still allowed).
Now, whenever I try to apply the solutions found for SirGive to my case, Iâm faced with the same issue: casting my animatorâs RuntimeAnimatorController as an AnimatorOverrideController gives me Null.
This code first displays âOriginal controller = Character (UnityEngine.AnimatorController)â, and then "Override controller = " in the console.
I am now testing 5.6.0b4 (tested on 5.4 and 5.5 before that), and I still canât manage to properly get rid of the nesting and still have my overridings work.
It would be great if someone could help me find a solution for thatâŚ
Hey, I got this working for my situation, not sure about layers yet though⌠basically, I have two WeaponInstances: Left and Right, but not sure if Iâll have one, both, or neither, etc. So I had to figure out a way to see if there was a âLeftâ animation, if not, then just keep the âRightâ animation, but if there is no âRightâ animation, or âLeftâ, then just keep the base.
Hereâs what I came up with, using the AnimationClipOverrides class from the 5.6.x documentation.
public void OverrideAnimationClip(UserEntityView aView)
{
Animator animator = aView.Animator;
AnimatorOverrideController myOriginalController;
AnimatorOverrideController myCurrentOverrideController = animator.runtimeAnimatorController as AnimatorOverrideController;
if (myCurrentOverrideController != null)
{
myOriginalController = myCurrentOverrideController.runtimeAnimatorController as AnimatorOverrideController;
}
else
{
myOriginalController = animator.runtimeAnimatorController as AnimatorOverrideController;
}
// this is a cs class, not a mono or scripbable...
// I know I should move this to an init function, but whatever :smile:
if (overrideController == null)
{
overrideController = new AnimatorOverrideController(animator.runtimeAnimatorController);
animator.runtimeAnimatorController = overrideController;
}
if (clipOverrides == null)
{
clipOverrides = new AnimationClipOverrides(overrideController.overridesCount);
overrideController.GetOverrides(clipOverrides);
}
if (_idle != null)
{
clipOverrides["Idle"] = _idle;
}
else
{
if(myCurrentOverrideController["Idle"] != null)
{
clipOverrides["Idle"] = myCurrentOverrideController["Idle"];
}
else
{
clipOverrides["Idle"] = myOriginalController["Idle"];
}
}
if (_run != null)
{
clipOverrides["Run"] = _run;
}
else
{
if (myCurrentOverrideController["Run"] != null)
{
clipOverrides["Run"] = myCurrentOverrideController["Run"];
}
else
{
clipOverrides["Run"] = myOriginalController["Run"];
}
}
if (_auto != null)
{
clipOverrides["Auto"] = _auto;
}
else
{
if (myCurrentOverrideController["Auto"] != null)
{
clipOverrides["Auto"] = myCurrentOverrideController["Auto"];
}
else
{
clipOverrides["Auto"] = myOriginalController["Auto"];
}
}
overrideController.ApplyOverrides(clipOverrides);
}
Iâve moved to the ApplyOverrides method, but I found the performance to be terrible, in the 100ms range range for a single call, with an extra 40ms on Animator.SetupControllerDataSet (called once for every animation?). For reference, our Animator has ~300 animations.