Animator locking animated value even when current state has no curves/keys for that value

I just had this problem now -

My gameobject was in the default state, doing NOTHING (has an animator applied, but not yet entered an animatable state). I couldn’t change the localScale programatically to be 0,0,0. Even with write defaults off, the next frame the scale jumps back to 1,1,1

I fully expected that

  1. in a state where no animation takes place, you can tweak the transforms/properties of the object and any future states will start from the current values unless curves are set to explicitly override those values.
  2. In a state that animates say, only position.x, that scale, or position.y could be altered independently by code (unless Write defaults is on).

Without hacking into LateUpdate.

1 Like

I know I’m beating a dead horse at this point with all the complaints here about the issue already, but why would this possibly be not only the default behavior but completely unmodifiable? As many have said already, anybody would intuitively expect it to only overwrite values that are utilized by the currently active animation.

Many people here have presented the solution of disabling the animator component when not in use, but that’s not an option when you have an idle state and animations to cover every potential player state requiring the animator to always be active. I tried disabling “Write Defaults” as suggested by many here, but that didn’t fix anything. I’ve confirmed that it’s only one animation state within the controller causing the issue by removing it temporarily. Even so, setting the sole problem state to not “Write Defaults” fails to fix the issue of constantly overriding the value even when there are no transitions associated with the state. I’m just completely at a loss as to why this would be considered desirable behavior, and still utterly ignored after years of complaints.

At least now that I know this is an issue I can work around it. I would never have expected the animator to be causing this sort of problem though, so I didn’t think to check the documentation for the animator when the bug first occurred. Only after an hour or two of bug tracking did I find out it was a single animation state that was never touched in my tests causing the issue.

Edit: Forgot to mention, the LateUpdate solution is also not always an option. If you’re calling a method via Invoke, a physics trigger, a callback, etc then you don’t really have that freedom as far as I know. That could just be by inexperience showing, though.

4 Likes

Similar issue with a blink anim.
Player has Idle anim and on the hierarchy I have a blink animation that randomly triggers.
The Player other anims uses the blink morph controllers.
Now if the blink controller is in Empty state then when playing other anims that uses blink rig controllers they play wrong because the blink controller overwrites them.
So the current behaviour is:

  1. A overwrites B
  2. A finishes an animation → write A.defaults
  3. A has empty animation, A.defaults overwrites B animation

Expected behaviour (Solution)

  1. global defaults
  2. A overwrites B
  3. A finishes an animation → write Global.defaults
  4. A has an empty animation, B non empty animation overwrites Global.defaults

If it’s possible to implement this, as there is no elegant animation solution to this, except disabling the blink anim controller…

I’m not expecting much to change here going by what’s already been posted, but just wanted to share my experience here since I also struggled with this limitation.

Basically I’m making a Kinect game for a university course where the player controls an Owl, with the wings being mapped to Arm movements in script. The player can trigger an animation where the owl forms its wings into more of a ball shape when performing a specific gesture.

The whole process of having the wings controlled by code most of the time, but through an animation when triggering this gesture ended up being way more complicated than necessary due to the inability to modify values that are animated in any state of the animator.

In the end I went with the solution of only enabling the animator in that one specific instance, as a result I was forces to kind of smooth over the transition between script control and animator control in code, with the result falling slightly short of what I was hoping for. The point is: Having the animator overwrite values in states where no values should be written to makes no sense, the “Write Default checkbox” doesn’t seem to actually do anything (when from my understanding of its description it should fix precisely this problem) and the workarounds to achieving what I was looking for were sub-optimal.

I’m not holding my breath for this getting fixed, but come on…

You can see the problem very easily without even write code. if you had a ‘x’ value used by a single animation in your hole animation hierarchy, just try to modify that value in inspector during play mode; you cannot, even if that animation isn’t playing.

I think my case is even simpler:

2D Sprite animation: Walk

1st half of the animation the sprites just fine.
2nd half of the animation the sprites flip in x (so you save tex space)

As you move left or right, the sprite has to be flipped again x axis (by script obviously), oh but you cannot, because you have that value locked by the animator.

@Kybernetik I’m actually using that component but the issue still happens; maybe because the component requires Animator component anyways, it seems like the simple existence of the animation on game it’s enough

If it helps motivate @Mecanim-Dev and the Unity team, I’ll add in my two cents as well:

I’ve been working on a game where I have three heart elements in the UI, one of which exists by default, the other two are cloned off of the first in code. Naturally, I put the second and third hearts at different positions equally spaced from the default position driven by the first heart - again, I do this part in code. Each heart has several identical animations, including one specific animation, only used in one very specific scenario, that changes the Transform position of the heart.

Because of the sole presence of that specific animation, all the hearts, each frame, are moved to their default position that’s driven by the first heart, regardless of which animation state they’re in. In-game, that makes it look like there’s only one heart, when really there’s three, and the animator makes it incredibly difficult to move the second and third hearts off of the first heart’s default position.

To beat a dead horse (or maybe to add fuel to the fire, more optimistically), this was very unintuitive behavior to me, and honestly it just seems weird to figure out that this was intended. I can’t think of a good reason for this to be desirable behavior, though I understand that technical limitations may, for some reason, make it necessary behavior. I get that there are ways to work around this quirk, but unchecking Write Defaults doesn’t seem to do anything for me (like most everyone else in this thread), using LateUpdate to re-adjust animated objects’ positions every single frame seems like a very needlessly performance-heavy solution, and anything that involves disabling the Animator itself seems just as unintuitive and annoying as the quirk itself. For what it’s worth, I’m another person who would really appreciate seeing this intended behavior changed.

I’m quite happy I only wasted hours, not days trying to figure out if it is just me, or Unity doing some unintuitive magic again. Whoever came up with this and thought it is a good idea, please present us with one good use case. I am not seeing any. And even yet, if you want to keep it this way - why would you force it on us? Why not just give us an option to choose whether we want this behaviour or not with one simple checkbox? I just spent hours changing animations to less appealing ones just to make the game work properly.

10 Likes

This behavior caused me to waste almost an entire day. In our case, we had a group of animations in a single controller that set active/inactive on some UI elements. When we would get to an animation state that didn’t include a prior UI element, it would get set to the UI Element’s last active value, even though it wasn’t in the track list. We noticed that this was happening when we tried to toggle active/inactive in the inspector but something was locking the value. Turns out it was Animator.

The expected behavior here is that only the tracks that are in the active animation should be affected.

Our solution is to manage active state in code and remove all tracks relating to Active from the entire animation controller.

This problem could be solved though by introducing a root object for your heart that you don’t animate. E.g.:
HeartRoot
|—Actual heart (Put Animator here)
|—|—Graphics

By animating locally in your hierarchy rather than the root object, you should be able to retain your offset position since that position is specified on the Root object. The root object should just be an empty game object.

I also experienced issues with an animator applying defaults and overriding my code. I basically have an idle animation where the character bobs slightly, but the mouth sprite needed to change for the talking animation. The enabled property of the SpriteRenderers was getting set by the animations even though I wasn’t animating them. I tried to set the enabled property in the animations but state transitions in the animator put an end to that real quick.

I ultimately had to set some bools in my speaking coroutine and have the proper mouth sprite enable/disable in LateUpdate every frame the character is talking. There’s no performance hit that I can notice, but if unchecking “Write Defaults” worked as intended it would not have been an issue.

I just spent a whole day debugging why setting a simple transform.rotation wouldn’t work in code… after i figured that the animator is causing this lockdown :eyes: … i just set my rotation to be set (before i set my object active) But in the near future i will want to use idle animation and not disabling the the object at all - what do i do then?

Is Unity having plans to improve on this behaviour? It really is just headaches as it is behaving at the moment!

2 Likes

Crazy it’s been 2 years since the dawn of this thread. I have a question which is nagging me: Are we using animations correctly? I commonly set up the graphics for my objects in a separate child from the main collision/ AI parent object. This seems to be best practice, as far as I’ve seen. But seeing as unchecking the “write defaults” checkbox does not cease the writing of values as defaults (Iron clad defaults, as we’ve found, with the exception of LateUpdate), are we supposed to animate changes in the transform in some other fashion than the “add property” tab in the animation editor window?

The issue I am facing is that I have an enemy death animation, where the enemy (which is part of a pool) shrinks and spins up into the sky (kinda like what happens when you cause an extinction event in SPORE). The child object gets pushed from a y position of 0, to a y position of 3. Then I have an event at the end of the animation which disables the parent root object, returning the parent and all children to the enemy object pool. When that object is next spawned, the parent transform is fine, but the child (with the graphics) is stuck at a y position of 3. Additionally, before the animation has been played, that child is stuck at a y position of 0 (which is technically unnoticeable because it’s grounded, but that’s where the animation starts, so… still an issue, even if not evident).

If anyone has a solution, a better practice, or an update on the status of a Unity response the animation property lockdown, I would greatly appreciate it. :slight_smile:

Since my last post I’ve actually tested the behaviour of the Simple Animation component and found that the behaviour described under the headding “SimpleAnimation doesn’t support only writing the values of the current clip by default” doesn’t actually work as they say. After adding a property to expose keepStoppedPlayablesConnected publicly to make it actually usable, I found that it does indeed disconnect stopped playables from the graph, yet that still doesn’t prevent them from writing the values of all their curves every frame (i.e. locking the animated values). I submitted a bug report (case 1143585) and they were able to reproduce it, but I haven’t heard anything else since.

@MadboyJames_1 Try out my Animancer plugin (link in my signature). The issue you’re describing should not be a problem when you use it.

To be honest, that only makes this whole problem more confusing because Animancer doesn’t actually do anything to fix it, the problem simply doesn’t happen when using the Playables API. And since Mecanim uses the Playables API internally, that means the Animator Controller must be intentionally doing something extra which screws it up …

2 Likes

Interesting. That could very well work. My dilemma is I like the Animator GUI. It has decent organizational capacity for any object with, say, less than 10 animations (arguably only 5 or less). Good for prototyping. I’ll give Animancer a go.

Update: Animancer seems pretty solid (using Lite), but the issue I’m running into is being able to edit animations without adding in a AnimatorController. Do I just need to have the AnimatorController attached while editing, then delete the component once I’m done?

Update 2: Strangely enough, The animations are still locking my values, even with Animancer.

I meant that Animancer should fix the issue of animated values not resetting when you reuse a pooled object, not the issue with locking animated values while active. I haven’t found a solution for that one.

Unfortunately you do currently have to assign an AnimatorController to edit animations. But in Unity 2018.3 they introduced the ability for custom components to provide AnimationClips to the Animation window so I’ve added support for that in the v3.0 update I’m currently working on. I’m planning on releasing a beta once I finish the documentation in a couple of days so people can try it out and give me feedback while I make a trailer video and improve the store page. If it’s a big part of your workflow at the moment I can put together a package of the Lite version for you in the morning.

It would probably be best to send me a private message or post over here if you have any other questions about Animancer so we don’t derail this thread.

Edit: Animancer v3.0 is up on the store now.

Interesting problem! I had the same headache with Mechanim/Animation state with UI. For example,
I would like to fadeout a button (via script) then flash it. After creating an animationclip that animates alpha value, the whole UI element has been locked.
The fadeout effect via script has no effect since the animation state stays at ‘idle’ state that locks everything.

The only solution i found:
i have to manually disable the ‘animator’ component on my UI element.
When i want to play the ‘flash’ effect, i have enabled=true.

To me it is very unintuitive design. Or it is better to mention this some where…overwise, we will waste thousand hours on this topic.

thanks

1 Like

Agree with everyone else that this is really intuitive.

I have luckily found a solution that satisfies my needs.
My goal was to have an idle animation that bobs the hips up and down, but leaves the feet to use IK so that they may fall naturally on stairs etc.
The AnimatorOverrideController solution didn’t really work for me but I managed to get it working with Playables.
Basically you remove everything from your AnimationController as playables doesn’t need it. Then you can just call this:

 if (!animationClipPlayable.IsNull ())
            animationClipPlayable.Destroy ();
        animationClipPlayable = AnimationPlayableUtilities.PlayClip (GetComponentInChildren<Animator> (), randomClip, out graph);

The Destroy is to stop the previous animation playing if there was one.

wow this is a bug sold as a feature : 9 you have an animation on your character that moves the player transform just becaus eyou want to let it “slide” somewhere into bed for example, and then your pos and rotation is locked forever , except you turn off the Animator , lol jeeeez, even if you let the animcontroller run on a complete empty animation your pos and rot is still locked, my god…

Edit: To be fair, Timeline looks interesting for such “cutscenes” , but it also looks like a hack , adding an empty Animator

Update: look my message below how I solved this for my cases, maybe you can use the info to solve your case too!

2 Likes