• Unity
  • Snapping Issue

Currently I have my player aiming up and then when I move the player to either side the players arms aim to the side at a fixed angle. I have the aiming up animation set to track 0 and the aiming to the side animation set on track 1. Snapping occurs when transitioning from track 0 to track 1, as well as oversnapping, meaning the arms go below the animation pose required and snap back into place. How do I go about tackling oversnapping of joints between tracks.

Two days ago I saw a similar forum thread to this but I just searched for 20 minutes and could not find the referenced thread that I was searching for.

I used _track1 = state.SetEmptyAnimation(0, 1f); which reduced the snapping a lot but not entirely, you can still see it happening.

Tim

Related Discussions
...
tjbrunetto wrote

Snapping occurs when transitioning from track 0 to track 1, as well as oversnapping, meaning the arms go below the animation pose required and snap back into place.

Could you please show some screenshots that display what you mean by "oversnapping" and "the arms go below the animation pose "?

Hi Harald,

The arm when coming down from the Upper Aiming Pose goes down very far and then snaps back into place. Here is a video to show you what I am looking at.

I have uploaded a video 5 times and it is not working using the Upload Attachment underneath, it says it downloads then I upload it and it seems to disappear. Is there an email I can send this to?

Tim

Sorry about that. Maybe it's over the forum upload file size limit, though the forum should give an error. Anyway you can send via email: contact@esotericsoftware.com

Thanks for the video, now I see what you mean.

I'm not completely certain what your character animations and code look like, could you please also send us your exported assets and the code you used to setup and transition the animations? This will save us the time tossing questions and answers back and forth.

Maybe I can skip the request of sending you all of the code, the scripts are quite long and I would have to photoshop them to show you guys exactly what to look for. The issue is going between tracks 1 and 0. When aiming up you are on track 0 and when moving the arm down to aim and run to the right the arms are on track 1. I wanted to clear the animation state on track 0 so that track 1 would not need to snap in place but even when doing so that is an issue. If you still need to see the code, I can take some time to gather this for you so you can see exactly what is going on.

Tim

Maybe I can skip the request of sending you all of the code, the scripts are quite long and I would have to photoshop them to show you guys exactly what to look for.

As you like. No need to mark anything though, we usually have no problem finding the necessary parts. We would need to see at least how you perform the following AnimationState and TrackEntry related tasks:

  1. Start the animations on tracks 0 and 1

  2. Transition / Alpha blend between the tracks

Regarding your animations:
Are they a single frame each, aiming at the target direction?

The aiming animations are on track 1 which control the upper body only. The running animation which controls only the lower body is on track 0. The animations are 24 frames long so 1 second each with the dope sheet running at 24 fps. I will send over the code that you guys need to your email so you can find the necessary code.

It may be easier to use the Preview view to simulate what you want to do (or the Skeleton Viewer, which is similar). If you try a sequence of animations using one of those and it doesn't work like you expect, you could send your Spine project and instructions on how to repeat the sequence.

Nate is your previous comment after I sent you the code via email? Did you guys receive the code snippets.

Yes we received your email but I haven't had time to look into it. Harald will be on that as soon as he gets a chance. However, a big block of code is not enough to reproduce the problem without us trying to write the rest of your app. I stand by my advice to: 1) give step by step instructions on how to click around in Preview, 2) explain what you think should happen, 3) explain what you see instead. Otherwise I expect Harald will ask you for code he can run to see the problem, which means you'll need to simplify your Unity project down to the minimum that shows the problem (or create a new, simpler project) and send that.

I sent a video to you guys, the process is exactly as you explained to me. Let me know if there is anything else that you need from me.

Thanks for the email, we received both code and video, especially the video shows your setup and desired outcome very well, and with the code I now know how you trigger and transition between your animations.

In general, seeing the very long lines of code at the if-conditions (you must have a pretty wide monitor to fit the 480 characters 😉 ) lets some alarm bells ring. It would be far less error-prone to separate common conditions in an enclosing if-block instead of repeating them. In addition, all your if conditions are of the form if, if, if instead of if, else if, else if which could enter multiple of the branches (each starting another animation), which should be exclusive.

Btw: you seem to have an error in your code:

_track1 = state.SetAnimation(0, _pistolsAimingUp0, true);

The above line assigns the track entry of track 0 to your _track1 variable.

Have you tried what happens if you only start a simple set of your animations without any game logic (even your gamepad could cause problems on the input side)? It would be best to create some minimal code that starts the problematic animations in a hardcoded way, to easily reproduce the problem.

Could you please send us your exported assets as well, then we can have a look at it.

Hi Harald,

I could definitely move all of the conditionals to the enclosing if and not repeat them, the only reason that I do that is to increase the amount of guard code so that less errors occur. If I am mistaken in my thought process I can easily switch all of that out. Also I switched up a lot of the if and else if statements so that every code snippet does not need to get run through. I do assign track entry to track 0 because when I set the animation to track 1 it bugs the game out, I was having trouble rigging that up to work the other day. The issue started when I got it to work as expected and then the snapping started to occur.

When you refer to the exported assets, your specifically referring to the character rig itself through spine?

Tim

tjbrunetto wrote

When you refer to the exported assets, your specifically referring to the character rig itself through spine?

I mean the three file that you place in the Unity asset dir, so e.g. the .json, .atlas.txt and .png file in case of json export.

4일 후

Harald, I sent all of the information over to you and sent another video showing you my current issue. The issue is the same as the one I have been describing thus far. Let me know if you also received the exported assets.

Tim

Thanks for the assets and videos. I see that you are using Spine version 3.7.93 to export the assets. Which version of the spine-unity runtime are you using? This dipping issue should already have been fixed on the runtime side.


To avoid dipping on track 1, you can set the TrackEntry holdPrevious parameter to true.

Please note the documentation page:

" When mixing between animations that key the same property, if a lower track also keys that property then the value will briefly dip toward the lower track value during the mix. This happens because the first animation mixes from 100% to 0% while the second animation mixes from 0% to 100%. Setting holdPrevious to true applies the first animation at 100% during the mix so the lower track value is overwritten. Such dipping does not occur on the lowest track which keys the property, only when a higher track also keys the property.
Snapping will occur if holdPrevious is true and this animation does not key all the same properties as the previous animation."

So the precondition is that you need to key the same properties as the previous animation, which will be the case in your animation IIRC.

5일 후

Please note that the way to use hold previous is to set it to true on all track entries for track 1. Also, when using hold previous, all animations on track 1 must key all the same properties. If not, then you may see snapping when the mix duration has elapsed (when the old animation keys something the new one doesn't). The only exception is if you are using an empty animation to mix out the animation on track 1, then you should not set hold previous to true to allow the old animation to mix out.

In other words, any time you set or add an animation for a track, you get a TrackEntry. To use hold previous, any time you set or add an animation for track 1, you should get the TrackEntry and set HoldPrevious to true, as you have shown.

By "keying the same properties", I mean that all the animations used on track 1 should have timelines for the properties any of the other track 1 animations have timelines for. All timelines should have keys on frame 0. There is no requirement to set keys at the same times or have the same animation lengths.

It should help if you understand how it works, but brace yourself because thinking through AnimationState can be tricky!

Consider track 1 mixing from animation A to B. Normally A is mixed out while B mixes in. Let's say A and B key the same translation bone value. It is reasonable to expect the bone to not move during the mix, however if A mixes to the setup pose while B is mixing in, the bone translation will "dip" toward the setup pose, then B takes over and moves it back. This is the "dipping" problem you are seeing.

When dipping occurs on the lowest track that keys a property, we can fix it. When A is the first animation to key the bone translation, AnimationState knows it can safely apply A fully instead of mixing it out. This is safe because no lower track is keying the bone translation, so applying it fully won't overwrite values from other tracks. So A is applied fully, then B is applied mixing from A's position to B's position. This gives us the mixing we want, without any dipping. :greatsuccess:

However, we cannot apply such a fix if a lower track is keying the same property. Say Z is on track 0, A is on track 1, and then we are mixing from A to B on track 1. Z, A, and B all key the same bone translation (same or different values, doesn't matter). Z is applied first. Next A is applied, but we can't use the dipping fix because we want to apply A on top of the value Z sets. That is because A may be mixing in or have TrackEntry alpha set, so may mix with the value Z set. So we mix A out while we mix B in, and that causes dipping: the bone moves from A's position toward the Z's position as A is mixed out, then moves to B's position as B is fully mixed in. :headwall:

Now consider the same Z, A, B scenario when B has hold previous = true. Z is applied first. Next A is applied fully, because hold previous means that the previous animation is applied fully instead of being mixed out. Note that applying A fully means any value Z set is overwritten. Next B is mixed in, so the bone position mixes from A to B without any dipping.

Still with me? Good! :cooldoge:

Finally to get to my point: why do A and B need to key the same properties? Let's say Z and A keys a bone translation that B does not:

  • ​Without hold previous​​, ​first ​​Z is applied. Next ​A ​is applied mixing out: over the mix duration the bone position moves from A's position to Z's position. Lastly B is applied and the bone is not changed since B does not key it.​ When the mix from A to B is finished, A is no longer applied and the bone is at Z's position.

  • ​With hold previous​, which we need to fix dipping, ​first ​​Z is applied. Next A is applied fully, so the bone is set to A's position (the position set by Z is overwritten). Lastly B is applied, which doesn't change the bone. When the mix from A to B is finished, A is no longer applied so the bone jumps from A's position to Z's position. Such jumping is undesirable. :scared:

  • ​How to fix this? B should set a key for the bone. Then​ with hold previous​, ​first ​​Z is applied. Next A is applied fully, so the bone is set to A's position. Lastly B is applied mixing in, so the bone position changes from A's position to B's position. When the mix from A to B is finished, A is no longer applied and the bone is at Z's position without any jumping.

Ideally that makes sense to you. ​If all that is t​oo much, then just follow the advice that all your track 1 animations have timelines for the same properties. :wounded:

​Note that another way to setup your skeleton, as mentioned in the issue, is to not key the bones in track 0 animations that you want to control in track 1 animations. This will make the dipping go away because AnimationState can fix it, as described above. If you were keying bones on track 0 for an idle animation, you could instead apply the idle animation on track 2 using additive. This means first the animations for tracks 0 and 1 are applied, then the animation for track 2 is applied by adding the keyed values to what was set by lower tracks. To do that set TrackEntry mixBlend to MixBlend add.

You can experiment using the Preview view. I don't suggest building all the animations and implementing it at runtime until it is working like you want in Preview. You can set the speed to very slow or even 0 to give yourself time to queue up other animations in Preview.

5달 후

Nate thank you for the lengthy reply. I appreciate you and the rest of your teams drive to keep us all informed.

Tim


Hi guys,

So I have hired a coder to take on the challenge of taking my code and making it a lot more efficient for my game. Now I have questions on how to use hold previous in conjunction with the keys that are keyed in Spine. Do I need to key everysingle keyframe and make sure that every single thing has a control variable on it? I am having trouble understanding this line in particular.

The animation that I am keying to is in fact, a nothing animation, and you are saying not to use hold previous if that is the case. Then how do I get rid of the arm dipping issue. Track 0 is the idle animation, and track 1 and 2 are being mixed together in order to produce the aiming animation. The arm dips when those two tracks (1 and 2) are being phased into the nothing animation and track 0 is taking over and starting the idle animation.

Tim