Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
5
Question by deeds0l · Mar 10, 2015 at 02:42 AM · animatormechanimstates

Parameters and States of Animator Reset on Object's Disable

Hi whenever I disable an object with an animator or its parent the animator states and all its parameters go back to default. In addition the object still stays where I animated it, for example is I have the object animated in its x axis + 5; the object still stays in the positive 5 position even if the states and all its booleans are reset. I was wondering if there is a work around to this so that when I reenable the objects the states stay the same from where I left it.

Comment
Add comment · Show 2
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image lordlycastle · Mar 30, 2015 at 06:26 PM 0
Share

The states shouldn’t go back to default, they should stay the way they were when disabled. Could you provide the code you use, and some more context.

avatar image art_craft_vlad · Dec 09, 2015 at 03:41 PM 0
Share

We have just faced the same issue in our project. We have a complex state machine with a long list of parameters on our enemy objects. When an enemy is killed we are setting the parameters to play proper 'dead' animation. The body supposed to stay visible for all time. However, when the Renderer is beco$$anonymous$$g invisible, the Animator is reset to its default state and as well as all the parameters. So, next time you see a dead enemy it plays its default animation. I am going to adopt FamerJoe's solution to our case, but I feel like such functionality needs to be provided by the engine itself. Please vote to bring Unity attention to the issue.

4 Replies

· Add your reply
  • Sort: 
avatar image
5
Best Answer

Answer by FamerJoe · Mar 30, 2015 at 08:54 PM

I had the same problem, where I wanted to hide the character during teleportation; I did create this workaround. Unfortunately, by the time OnDisable is called, the anim.parameters array is empty (probably another bug), so you actually have to call OnAnimDisable before disabling the object. Then, the state will be saved and restored OnEnable. Just attach this script to the object with the Animator on it. I don't know if this will work for triggers though, as I don't use any in my project. It works for bools, floats and ints though.

 using UnityEngine;
 using System.Collections;
 using System.Collections.Generic;
 
 public class PreserveAnimatorOnDisable : MonoBehaviour {
 
     private class AnimParam {
         public AnimatorControllerParameterType type;
         public string paramName;
         object data;
 
         public AnimParam (Animator anim, string paramName, AnimatorControllerParameterType type) {
             this.type = type;
             this.paramName = paramName;
             switch (type) {
             case AnimatorControllerParameterType.Int: 
                 this.data = (int)anim.GetInteger(paramName);
                 break;
             case AnimatorControllerParameterType.Float: 
                 this.data = (float)anim.GetFloat(paramName);
                 break;
             case AnimatorControllerParameterType.Bool: 
                 this.data = (bool)anim.GetBool(paramName);
                 break;
             }
         }
         public object getData() {
             return data;
         }
     }
 
     Animator anim;
     List<AnimParam> parms = new List<AnimParam>();
 
     void Start() {
         anim = GetComponent<Animator>();
     }
 
     public void OnAnimDisable() {
         Debug.Log("Saving Animator state: " + anim.parameters.Length);
         for (int i = 0; i < anim.parameters.Length; i++)
         {
             AnimatorControllerParameter p = anim.parameters[i];
             AnimParam ap = new AnimParam(anim, p.name, p.type);
             parms.Add(ap);
         }
     }
 
     void OnEnable() {
         Debug.Log("Restoring Animator state.");
         foreach(AnimParam p in parms)
         {
             switch (p.type)
             {
             case AnimatorControllerParameterType.Int:
                 anim.SetInteger(p.paramName,(int)p.getData());
                 break;
             case AnimatorControllerParameterType.Float:
                 anim.SetFloat(p.paramName,(float)p.getData());
                 break;
             case AnimatorControllerParameterType.Bool:
                 anim.SetBool(p.paramName,(bool)p.getData());
                 break;
             }
         }
         parms.Clear();
     }
 }
 
Comment
Add comment · Show 5 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image deeds0l · Apr 06, 2015 at 08:12 AM 0
Share

Just a quick question what is AnimatorControllerParameterType is that an enum you declared somewhere? anim.param is also not recognised in the animator component.

avatar image FamerJoe · Apr 06, 2015 at 01:40 PM 0
Share

AnimatorControllerParameterType is Unity5 only. Also, I call anim.parameters, not anim.params ?

avatar image deeds0l · Apr 07, 2015 at 09:29 AM 0
Share

Is there any alternative for these since I'm using unity 4.6.2?

avatar image FamerJoe · Apr 07, 2015 at 12:39 PM 0
Share

Not sure, you'd have to look into it

avatar image Gotama · Sep 23, 2017 at 12:35 PM 0
Share

Worked for me. Thanks.

avatar image
16

Answer by Skeldal · Mar 17, 2020 at 08:10 AM

For those who hit this thread recently (and use at least Unity 2018.1), use Animator.keepAnimatorControllerStateOnDisable = true.

Comment
Add comment · Show 4 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Elkis · Mar 20, 2020 at 05:59 AM 0
Share

Thank you!

avatar image RedHillbilly · Nov 05, 2020 at 06:25 PM 0
Share

If i'm not mistaken, works for states but not parameters, right?

avatar image DungDajHjep · Mar 22, 2021 at 03:30 PM 0
Share

you save me, my god !

avatar image ProbePLayer · Aug 04, 2021 at 02:28 PM 0
Share

oi, this did the trick, thanks!

avatar image
0

Answer by wallstop · Feb 20, 2018 at 06:24 PM

Here's a script that will restores full state, including current animation and progress within the animation, as well as trigger values. @deeds0l

     /// <summary>
     /// Will restore an Animator to it's full state whenever it's game object is disabled or enabled.
     /// </summary>
     /// <note>
     /// Requires the animator to be BENEATH this component in the component heirarchy on the object.
     /// Nothing special required for script execution order.
     /// </note>
     [RequireComponent(typeof (Animator))]
     public sealed class RehydrateAnimator : MonoBehaviour
     {
         private Animator _animator;
 
         private readonly Dictionary<int, AnimatorStateInfo> _stateInfoByLayer;
         private readonly Dictionary<AnimatorControllerParameter, object> _parameterValues;
 
         public RehydrateAnimator()
         {
             _stateInfoByLayer = new Dictionary<int, AnimatorStateInfo>();
             _parameterValues = new Dictionary<AnimatorControllerParameter, object>();
         }
 
         private void Start()
         {
             _animator = GetComponent<Animator>();
         }
 
         private void OnEnable()
         {
             if (!_animator)
             {
                 return;
             }
 
             foreach (KeyValuePair<int, AnimatorStateInfo> layerAndStateInfo in _stateInfoByLayer)
             {
                 int layer = layerAndStateInfo.Key;
                 AnimatorStateInfo stateInfo = layerAndStateInfo.Value;
                 _animator.Play(stateInfo.shortNameHash, layer, stateInfo.normalizedTime);
             }
 
             foreach (KeyValuePair<AnimatorControllerParameter, object> parameterAndValue in _parameterValues)
             {
                 AnimatorControllerParameter parameter = parameterAndValue.Key;
                 object value = parameterAndValue.Value;
                 switch (parameter.type)
                 {
                     case AnimatorControllerParameterType.Bool:
                         _animator.SetBool(parameter.name, (bool) value);
                         break;
                     case AnimatorControllerParameterType.Float:
                         _animator.SetFloat(parameter.name, (float) value);
                         break;
                     case AnimatorControllerParameterType.Int:
                         _animator.SetInteger(parameter.name, (int) value);
                         break;
                     case AnimatorControllerParameterType.Trigger:
                         if ((bool) value)
                         {
                             _animator.SetTrigger(parameter.name);
                         }
 
                         break;
                     default:
                         continue;
                 }
             }
 
             ResetInternalState();
         }
 
         private void OnDisable()
         {
             ResetInternalState();
             if (!_animator)
             {
                 return;
             }
 
             for (int i = 0; i < _animator.layerCount; ++i)
             {
                 _stateInfoByLayer[i] = _animator.GetCurrentAnimatorStateInfo(i);
             }
 
             foreach (AnimatorControllerParameter parameter in _animator.parameters)
             {
                 object value;
                 switch (parameter.type)
                 {
                     case AnimatorControllerParameterType.Bool:
                     case AnimatorControllerParameterType.Trigger:
                         value = _animator.GetBool(parameter.name);
                         break;
                     case AnimatorControllerParameterType.Float:
                         value = _animator.GetFloat(parameter.name);
                         break;
                     case AnimatorControllerParameterType.Int:
                         value = _animator.GetInteger(parameter.name);
                         break;
                     default:
                         continue;
                 }
 
                 _parameterValues[parameter] = value;
             }
         }
 
         private void ResetInternalState()
         {
             _stateInfoByLayer.Clear();
             _parameterValues.Clear();
         }
     }
Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image gdbjohnson3 · Feb 02, 2019 at 09:19 PM 0
Share

I get an error that the Animator is not playing an AnimatorController with this script. I thought it might be my version of Unity (2017) but it doesn't seem like it. Once the Animator is disabled, it seems that this won't work. Am I missing something, or maybe this was resolved in the later version of Unity?

avatar image
0

Answer by RedHillbilly · Nov 05, 2020 at 06:34 PM

Might be useful for somebody else: I used @Skeldal's solution but couldn't use @FamerJoe's solution (not working in this case) to swap the animation override controller at runtime, so I also used parts of @wallstop's answer. I also needed the layer weights to remain so I added this as well. I expressed the code as an extension of the Animator class, so you can call the function on the animator itself:

 animator.SwitchAnimatorController(newController);

With the extension looking like this:

 using System.Collections.Generic;
 using System.Linq;
 using UnityEngine;
 
 public static class AnimatorEx
 {
     public static void SwitchAnimatorController(this Animator animator, RuntimeAnimatorController animatorController)
     {
         // save states
         List<AnimParam> parms = SaveAnimationStates(animator);
         float[] layerWeights = SaveLayerWeights(animator);
         AnimatorStateInfo[] animatorStateInfo = SaveLayerStateInfo(animator);
         
         // swap
         animator.runtimeAnimatorController = animatorController;
         
         // restore states
         RerstoreAnimationState(parms, animator);
         RestoreLayerWeights(animator, layerWeights);
         RestaureLayerStateInfor(animator, animatorStateInfo);
     }
 
     private static AnimatorStateInfo[] SaveLayerStateInfo(Animator animator)
     {
         int animatorLayerCount = animator.layerCount;
         AnimatorStateInfo[] animatorStateInfo = new AnimatorStateInfo[animatorLayerCount];
         for (int i = 0; i < animatorLayerCount; i++)
         {
             animatorStateInfo[i] = animator.GetCurrentAnimatorStateInfo(i);
         }
         return animatorStateInfo;
     }
 
     private static void RestaureLayerStateInfor(Animator animator, AnimatorStateInfo[] animatorStateInfo)
     {
         for (int i = 0; i < animator.layerCount; i++)
         {
             animator.Play(animatorStateInfo[i].shortNameHash, i, animatorStateInfo[i].normalizedTime);
         }
     }
 
     private static float[] SaveLayerWeights(Animator animator)
     {
         int animatorLayerCount = animator.layerCount;
         float[] layerWeights = new float[animatorLayerCount];
         for (int i = 0; i < animatorLayerCount; i++)
         {
             layerWeights[i] = animator.GetLayerWeight(i);
         }
         return layerWeights;
     }
     
     private static void RestoreLayerWeights(Animator animator, float[] layerWeights)
     {
         for (int i = 0; i < layerWeights.Length; i++)
         {
             animator.SetLayerWeight(i, layerWeights[i]);
         }
     }
 
 
     private class AnimParam
     {
         public AnimatorControllerParameterType type;
         public string paramName;
         object data;
 
         public AnimParam(Animator animator, string paramName, AnimatorControllerParameterType type)
         {
             this.type = type;
             this.paramName = paramName;
             switch (type)
             {
                 case AnimatorControllerParameterType.Int:
                     this.data = (int) animator.GetInteger(paramName);
                     break;
                 case AnimatorControllerParameterType.Float:
                     this.data = (float) animator.GetFloat(paramName);
                     break;
                 case AnimatorControllerParameterType.Bool:
                     this.data = (bool) animator.GetBool(paramName);
                     break;
             }
         }
 
         public object getData()
         {
             return data;
         }
     }
 
     static List<AnimParam> SaveAnimationStates(Animator animator)
     {
         List<AnimParam> parms = new List<AnimParam>();
         foreach (AnimatorControllerParameter p in animator.parameters)
         {
             AnimParam ap = new AnimParam(animator, p.name, p.type);
             parms.Add(ap);
         }
         return parms;
     }
 
     static void RerstoreAnimationState(List<AnimParam> parms, Animator animator)
     {
         foreach (AnimParam p in parms)
         {
             switch (p.type)
             {
                 case AnimatorControllerParameterType.Int:
                     animator.SetInteger(p.paramName, (int) p.getData());
                     break;
                 case AnimatorControllerParameterType.Float:
                     animator.SetFloat(p.paramName, (float) p.getData());
                     break;
                 case AnimatorControllerParameterType.Bool:
                     animator.SetBool(p.paramName, (bool) p.getData());
                     break;
             }
         }
     }
 }

It might be a bit more heavy computationally though since it creates a new list each times, but I don't think it's much, and it's a bit more practical since you don't need to add the script to the GameObject. Hope it helps somebody :)

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

32 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Imported Blender Animations not Working 2 Answers

How to change animation clips of an animator state at runtime? Is there a way? 5 Answers

How can I get the legnth of an animation? (Mechanim Animator/C#) 2 Answers

Mechanim - should be simple, but... 2 Answers

How to achieve this EXTREMELY SIMPLE task with Mechanim? 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges