Can we make it so animations implicitly animate all unkeyed bones back to their setup position?

We have an animation that rotates a particular bone. That bone is not rotated by any other animation. We are seeing a bug in our game where that bone is 'stuck' in the rotated state, because no animation is keying that bone back.

Related Discussions
...

It's not easy to know which properties have not been keyed. It's a bit of wasted effort to set all properties every frame, but you can do it using Skeleton setToSetupPose.

How are you applying animations? AnimationState manages setting keyed properties back to the setup pose when they are no longer animated. The only exceptions to that are if you use clearTrack or clearTrack. If that is the case, use setEmptyAnimation instead.

Hmm. I'm doing some testing here and it seems like unkeyed bones do go back to their setup position. At this point I have no idea why certain bones are 'getting stuck':
Here's an example of what I'm trying to debug:

I'm using the godot runtime...

We're doing stuff like this:

spine_sprite.get_animation_state().set_animation("Death", false)

And some more complex ones:

state.set_animation("Land", false)
var current_track := state.get_current(0)
current_track.set_mix_duration(.0)
state.set_animation("Spawn", false)
spine.get_skeleton().set_bones_to_setup_pose()
var current_track := state.get_current(0)
current_track.set_mix_duration(0.0)

And some set_time_scale().

I'm unable to reproduce the bug in my testing, but in the game itself it happens. I'm unsure as to the cause.

All animations play on track 0.

That code looks fine and should not leave a bone with some non-setup pose value, since you never explicitly clear the tracks.

When an animation plays, by default it continues to be applied even past it's duration. If it's not looping, the animation will keep applying the last frame of the animation. Could you be doing that? That could cause it to appear a pose is "stuck". If so, you can queue an empty animation so the first animation is no longer applied when it reaches the animation duration.

Sorry there is one more way to not get setup pose values after an animation is done: if you set TrackEntry trackEnd then the track is cleared when the trackTime reaches the trackEnd time. You don't seem to be setting trackEnd though.

When an animation plays, by default it continues to be applied even past it's duration. If it's not looping, the animation will keep applying the last frame of the animation. Could you be doing that? That could cause it to appear a pose is "stuck". If so, you can queue an empty animation so the first animation is no longer applied when it reaches the animation duration.

Can you elaborate on this? We play some animations that are not looped (ie: Jump). But then we play a looping animation after (ie: Run).

It appears sometimes like a particular leg bone is in a weird place and it never seems to get corrected. ie: playing any of the animations does not correct that leg bone. I am unable to reproduce this issue in my testing where I rapidly force the character into different animation states.

It is starting to seem to me like this is perhaps a bug in the spine godot runtime? But it's weird that I cant reproduce it in my testing. Perhaps it's a bug that's only revealed by our application code, and I'm simply not reproducing our application code accurately enough in my testing.

  • Responderam a isso Nate.

    I'm looking through some of the more complex code, and I see this:

    Looks like a relavant block of code that could cause some issues like this:

    if just_landed:
        var track_entry := state.add_animation("Land", 0.0, false, 1)
        track_entry.set_alpha(intensity)
        state.add_empty_animation(1, 0.1, 0.0)

    That is 'add_animation(<animation_name>, <delay>, <loop>, <track>)andadd_empty_animation(<track>, <mix_duration>, <delay>).

    Note that this is a networked game and 'just_landed' could occur in sequential render frames.

    jasonknight Can you elaborate on this? We play some animations that are not looped (ie: Jump). But then we play a looping animation after (ie: Run).

    If you play an animation afterward then everything that the not looped animation keys is reset to the setup pose (nothing will be "stuck").

    jasonknight It appears sometimes like a particular leg bone is in a weird place and it never seems to get corrected. ie: playing any of the animations does not correct that leg bone.

    Do the other animations key that bone? If they do and the bone is still in a weird place, then maybe an animation gets played on a higher track and just stays there? You can iterate the tracks and check if they have an animation.

    You said earlier "All animations play on track 0" but the last code you posted uses track 1. Adding an empty animation will clear the track 1 animation (after mixing it to the setup pose over 0.1s) so it doesn't keep getting applied. Maybe there is some other case where the animation on a higher track is left to play forever?

    You said earlier "All animations play on track 0" but the last code you posted uses track 1

    Yes, sorry. The code using track 1 is from an earlier version of the software, that code no longer runs. I am working to verify if this issue is caused by the usage of track 1. Thanks for pointing me at the usage of multiple tracks, and for clarifying how keys work after animations finish.

    I've confirmed the issue is still present after the software was updated to not use track 1. (everything just on track 0)

    If a bone does get left in some pose (clearTrack, trackEnd, or possibly a bug), the next animation applied that keys the bone would set a new pose. Skeleton setToSetupPose would also clear the bad pose. If those don't get rid of the bad pose, then maybe some animation is being applied afterward to give you the bad pose. Another possibility is if you modify a setup pose bone instead of an instance bone (BoneData instead of Bone), then you'd see a bad pose no matter what animation you applied. All animations are relative to the setup pose.

    Ideally you could reproduce it in a test case, otherwise wait for it to happen in the game and debug it. You could look at what animations are being applied: both on each track and if there are multiple animations being mixed on a single track (TrackEntry next makes up a linked list). If you don't easily have a debugger, you could add code to Animation apply and print the animation name, so you can always see what animations are being applied.