Losing Animator State

What a disaster. If I disable a GameObject, Unity might as well destroy all the textures associated with it. That would free up memory.

Same issue… Have you provided the API yet?

1 Like

no, we added Animator.keepAnimatorControllerStateOnDisable to allow user to change the behaviour of the component when GO is disabled. Default value is false to keep backward compatibility with older project.

This is available in 2018.1a2 and can only be changed by a script

9 Likes

I just tried the keepAnimatorControllerStateOnDisable property. It does remember the state of the animator when the GO is disabled. But it doesn’t remember the default value of the animated properties. Therefore the “Write Defaults” option no longer works after the GO has been disabled and re enabled.

6 Likes

I found one workaround for this crazy bug:

  • In Animator controller we have Reset-state. One frame animation that reset everything to default
  • Before disabling the object we call Reset-trigger, than call Animator.Update() function, than call GameObject.SetActive(false).
  • Example:
_animator.SetTrigger("Reset");
_animator.Update(Time.deltaTime);
_gameObject.SetActive(false);
1 Like

I can confirm this solution works - thanks!

Please help this doesnt work for me!

Another bug with workaround for AnimatorController and deactivating/activating game object.
My Unity version is 2017.3.0f3.
Steps to reproduce the bug:

  1. Activate gameObject with animator controller first time. Add needed prefabs. Call Rebind() and SetTrigger().
  2. Wait for end of animation. Deactivate gameObject with animator controller.
  3. Activate gameObject second time. Clear old instantiated prefabs and add new ones. Call Rebind() and SetTrigger().
  4. On second time animation is completely broken. If run animation from Animation window in the preview mode everything will be restored and looks ‘ok’. Reactivating gameObject fixes the bug too.
    Workaround:
    Don’t call Rebind() right after activating the gameObject. Wait for LateUpdate() and call Rebind() here.

Bad example with bug:

public class BadAnimatedObject : MonoBehaviour
{
    public Animator animator;
    public Transform prefabParent;
    public Transform prefab;

    private Transform _prefabInstance;

    public void ActivateAndRunAnimation()
    {
        gameObject.SetActive(true);
        if (_prefabInstance != null)
        {
            Destroy(_prefabInstance.gameObject);
        }
        _prefabInstance = Instantiate(prefab, prefabParent);
        animator.Rebind();
        animator.SetTrigger("Run");
    }

    //Called from animation
    void OnRunAnimationComplete()
    {
        gameObject.SetActive(false);
    }
}

Good example with workaround:

public class GoodAnimatedObject : MonoBehaviour
{
    public Animator animator;
    public Transform prefabParent;
    public Transform prefab;

    private Transform _prefabInstance;

    public void ActivateAndRunAnimation()
    {
        gameObject.SetActive(true);
        if (_prefabInstance != null)
        {
            Destroy(_prefabInstance.gameObject);
        }
        _prefabInstance = Instantiate(prefab, prefabParent);
    }

    void LateUpdate()
    {
        enabled = false;
        animator.Rebind();
        animator.SetTrigger("Run");
    }

    //Called from animation
    void OnRunAnimationComplete()
    {
        gameObject.SetActive(false);
    }
}

hi @Andrey-Postelzhuk ,

would you like to log a bug for us with bad example? we would like to investigate this issue and see what is going on.

Thanks,

Hi @Mecanim-Dev
The problem has reproduced even in the most simple case. I’ve made simple project with bug example and reported it. Case number: 1071547

Note that in this example calling Rebind() in the LateUpdate() is not enough. To fix the bug it’s need wait for one frame. I think that the reason is in calling Rebind() from coroutine stack.

1 Like

works for me, thanks

I spent way too long trying to debug this ‘feature’ before i found this thread. As someone who does not normally work with animation but is used to the Unity convention of things being as you left them when you re-enable, this is a headache. Nice that we have the new code setting but can we not have this in the editor? I can almost guarantee this will trip me up again one day when i forget to enable the keepAnimatorControllerStateOnDisable in code. With presets and import settings we could make this default to what seems normal to us and we would never have to worry about it again.

1 Like

Is this problem still not solved? I just tried it, if my animated object was animated to a rotation of say 180 degrees when it was disabled, then on enable, as soon as the animation is completed, the GO returns to 180 degrees rotation, the value at the time the GO was disabled. This basically makes this feature unusable. I’m going to try and play with events to see if I can overcome this, but I’m worried anything I come up with will be buggy as hell.

If anyone has a workaround approach, I would appreciate hearing it.

– EDIT –

Reading the above quote, just as a lark after posting this, I tried turning off “Write Defaults” on the Controller, and voila, for me, the problem is solved. Since the animation exits at the values I want the GO to be at, I don’t get the undesired behaviour of the GO flipping to whatever values the GO was at when it was disabled. Of course, this is fragile, and I’m sure I’ll be running into more problems related to animations on disable soon.

keepAnimatorControllerStateOnDisable didn’t appear to do anything in my case

Edit: Back then I probably missed the interaction between nested animators. For example, I should enable keepAnimatorControllerStateOnDisable on a Button, and not on my UIPanel that holds the button.

My Animancer plugin (link in my signature) has a toggle in the Inspector (and in code) to determine whether it should stop all animations when disabled.

Incidentally, the reasoning that this behaviour is to conserve memory seems ridiculous to me. One of the most common reasons (if not the most common) to deactivate and reactivate objects is for object pooling, the main purpose of which is to improve performance by avoiding memory allocation and deallocation when reusing objects, not to conserve memory. Memory is cheap. Speed and functionality are almost always more important.

1 Like

Any news on when this bug will be fixed?

I’ve posted a potencial solution here: Animator locking animated value even when current state has no curves/keys for that value page-2#post-4934825

Would be cool with a simple way to make animator state persistent. Any news on a way to do this besides saving the state yourself?

Thanks for sharing good information

Me either. It’s only been 5 years though I guess we should still wait for a fix right?

2 Likes