Animation API acts funny, some parts not documented.

So there is some interesting things about the animation API, especially when it comes to using AnimationState.

It seems like Animation states, which animations are enabled, and more (I’m not sure what else) get reset when you disable / enable a gameobject with an animation. All the layers are set back to 0, for instance.

Is this intended functionality, and if so, why isn’t it documented? If not, what are the other pitfalls?

Some other weird things: If you play an animation by name, editing the animation state for that name takes effect, however if it is the default clip and you play it with Play(), changing the animation state for the default clip does not effect playback.

Animations set to Once have a normalizedTime at 0 once they finish playing, where I would expect they would sit at 1.0, Clamp forever does not finish playing, so if it was a 1 second animation, and you let it play for 8, setting the speed to -1 would not start the backwards animation for 7 seconds. I would expect it would start right away, or that Once would fulfill this role.

One other thing I don’t get about the animation API is why it insists on using Strings for looking up the animations states or referring to clips. We have the AnimationClip type and you would think it would be best to just pass in the object.

These are just comments, I don’t really care which way Unity implements animations as long is there is consistency with the documentation, and that stranger parts such as above are documented.

What other strange things have you guys noticed with Animations? Maybe if we talk about it we can get it worked out on our own.

bump

Disabling a game object will cleanup animation states, Instead you might want to look at the animation.enabled flag.

The usage of the animation API is usually that AnimationClips are automatically assigned to characters based on the importing of a model. Thus a script usually doesn’t have a reference to an actual animationclip. Thus in 99.9% of all use cases, the string based version is more handy. Easier to understand and nicely decouples the script from specific animationclips.

As far as I can see this works correctly for me. Do you have a sample project that shows the behaviour you describe? If so, file a bug with the project folder.

Possibly that would be the more intuitive behaviour. Of course it’s a bit more consistent the way it’s handled now, as in, the time value always progresses forward even when loop and pingpong is used. It’s something we can’t change at this point however for backwards compatibility reasons.
Just use AnimationState.time to set it to the right position when starting the animation backwards.

Here s some other great ones!

if you call an animation state function in OnEnable, animations will no longer work for that object.

Likewise, if you call an animation state function and the object is disabled, animations will no longer work for that object.

There is really not a good way to deactivate an object with an animation on it and keep state.

I ran into this same issue with my last project - I wanted to disable/enable my enemy gameObjects to hide them when they died or despawned, but it caused seriously bizarre results when I recycled them later by re-enabling them.

The workaround I used was to disable the mesh renderer and the script component, rather than the gameObject. In my case, this produced the same desired results (the object wasn’t running its script anymore and it was invisible) and didn’t have the side effect of mangling my animations when the object was reactivated.

I have here a summary of the problems.

  1. Deactivating and Reactivating a GameObject with an Animation clears all it’s AnimationStates.

  2. Any attempt to edit AnimationState on a deactivated object results in Animations no longer working on the object (even when they are re-enabled), and no errors are reported.

  3. Editing AnimationStates during OnEnable results in the same behavior.

  4. These problems also exist when using GameObject.SampleAnimation().

  5. Enabling, editing AnimationState, calling Sample(), and disabling also does not work, resulting in the same behaviour, though not always breaking Animations.

  6. Enabling and then editing Animation state after the object is re-enabled does not work, unless you use Play or CrossFade.

This results in a situation where it is impossible to save the state of an object with animations that can be deactivated. If you try to save when the object is deactivated, you will ruin the animations on it because you can’t access the state information.

If you try to set the animation to a saved version when the object is disabled, you will ruin it. If you dont try to set the animation until after you enable the object, animation states and Sample do not work until the animation has been played by .Play or .CrossFade at least once.

This requires building the game from the ground up to have all things with Animations have custom code for disabling and re-enabling.

Does anyone have more information on what is happening or solutions to the problem?

1 Like

Does the workaround I posted not work in your case? (disabling the renderer and script instead of the gameobject)

Did you guys find any better way to set a gameobject active/inactive and keep the animation states?

I ran into this problem too, and I think it’s also crashing my game on the iPhone when I get the error “The animation state could not be played because it is not attached to the animation component!
You have to provide an animation state that is attached to the same animation component.”
BTW, that error doesn’t even tell me where it tried to play an animation in the code.

Unfortunately, if you use Unity the way you’re supposed to (in a component-ized manner), you could have a variety of scripts and components attached to a GameObject that all need to be deactivated at the same time.

The animation system is a mess. Plain and simple.

I agree w Jerrod. Ran into this as well. Traversing every component of a core object (from outside of that core object) and toggling each component is a little silly. Ideally, I’d want to place high level controls at the container level and expect the container to manage the components. Not a tremendous amount of functionality but create/destroy and activate/deactivate seem pretty fundamental. My last project was an MMO where the number of components could reach up to 20+. As Jerrod points out there are times were you are required to release things in a specific order or all at the same time. There needs to be a management layer controlling that. Component patterns 101. I’m assuming that would be placed at the GameObject level in Unity.

Ah, thanks. I was seeing this problem, but at the time didn’t know what was wrong. I was setting the player object inactive upon death that had active blended animations, but whenever it was re-enabled, animations weren’t working correctly. I am guessing for the reasons Horsman listed.

My solution was exactly PirateNinjaAlliance’s: I just disabled the collider, rigidbody, mesh renderer, and the script that controlled the object’s movement.

I don’t like it, either.

This is especially annoying because it’s not possible to create a generic solution - you can’t just “get” all components on a GameObject! Otherwise one could just iterate through them and disable/enable everything but the animation component.

I was hoping for something like

public void SetEnabled(bool enable)
{
  foreach(Component component in gameObject.GetComponents())
  {
    if(!(component is Animation))
      component.enabled = enable;
  }
}

Too bad GetComponents always needs a type :frowning:

Hello, old thread but I found some other weird issues with the Animation system (2011) :

  • animation.Play() doesn’t trigger instantly, there is some delay. For example this code :
animation.Play("bindpose");

[ stuff here where you change the character's torso model 
bindposes remapping, bones remapping, etc
so you need to set the skeleton animation to a bindpose state]

Well, all the bindpose remapping model changing stuff will happen before the animation “bindpose” has started. Even if it’s placed after. It’s actually preventing correct bindpose remapping. “Bindpose” animationClip is one frame long, and always have the same transformations. So it should trigger the correct state instantly.

  • GameObject.SampleAnimation() nullify itself outside of the function where it was called. Example :
void Start(){

animation.Play("Walk");
ChangeTorso("armor2");

}

void ChangeTorso(string _armorName){
gameObject.SampleAnimation(animation["bindpose"].clip, 0f);

[ stuff here where you change the character's torso model 
bindposes remapping, bones remapping, etc
so you need to set the skeleton animation to a bindpose state]
}

Here, the SampleAnimation() function will correctly place the animation to “bindpose” state before the model change code block.
But after that function, the animation will automatically return to “Walk”. Wasn’t it supposed to stay in “bindpose” state at time 0f ?

  • Animation.Sample() doesn’t work like it should. Example this code :
animation["Walk"].normalizedTime = 0f;
animation["Walk"].enabled = true;
animation.Sample();

doesn’t work. Even if I perform no Play() before its call.
While :

gameObject.SampleAnimation(_modelAnim["Walk"].clip, 0f);

works perfectly.

Something is really weird inside this class :slight_smile:

Ok … About the Animation.Sample() not working, the documentation here :

didn’t mention that the Sample() function, unlike gameObject.SampleAnimation(), take into account the animationState weight. So as weights are by default set to 0 when the target animation is not playing, we have to manually set the animationState weight to 1f before calling Sample().
gameObject.SampleAnimation() automatically sets it to 1f.

GetComponents();

[quote=“n0mad, post:13, topic: 389721, username:n0mad”]
Hello, old thread but I found some other weird issues with the Animation system (2011) :

  • animation.Play() doesn’t trigger instantly, there is some delay. For example this code :
animation.Play("bindpose");

[ stuff here where you change the character's torso model 
bindposes remapping, bones remapping, etc
so you need to set the skeleton animation to a bindpose state]

[/quote]Maybe with coroutine:

IEnumerator MyMethod()
{
    animation.Play("bindpose");
    yield return null;
    [ stuff here where you change the character's torso model 
    bindposes remapping, bones remapping, etc
    so you need to set the skeleton animation to a bindpose state]
}

One issue I have is that the built-in “let Unity handle everything” animation methods do not put the AnimationState in a state that distinguishes it from DIY animation manipulation. E.g. if you enable an AnimationState and are manipulating its weight, time, etc. manually, its time is still being advanced in internal Unity code, overriding (adding to, actually) your manually set time value. Luckily, in this one instance, you can keep this from causing a problem by setting Speed to 0.

But the issue remains: If you are going to expose a low-level “DIY” animation api, then you need to distinguish between automatically updated AnimationStates and manually updated AnimationStates. OR, post the code (or more doc) for the automatic updates so that we can see what internal AnimationState manipulation we need to UNDO in our DIY code in order to get the anticipated result.

I have recently run into this problem. After testing a few things out and almost passing out from banging my head against the table, I came up with a work-around. It seems that just accessing the animation-object with a call to Animation.IsPlaying() in the gameobject’s Awake-method is sufficient to prevent the bugs from appearing. This is great news since you can easily make such a workaround script and assign it automatically to all game objects that have an animation component.

using UnityEngine;

public class ForceAnimationInitWorkaround : MonoBehaviour {

	// Use this for initialization
	void Awake ()
	{
	    if (animation != null) animation.IsPlaying("WHATEVER MAN!");
	}

    // Update is called once per frame
	void Update () {
	
	}
}

I have filed a report with Unity (Case 537045).

An interesting quirk is that if the game object with the animation is inactive from the beginning (that is, inactive in the scene view when we enter play mode), the animation will always work. Such inconsistent behavior on core functionality is really not flattering to Unity.