• Unity
  • 3.5+ Attachments And Mixing

Related Discussions
...

hi,

We are facing some trouble with the new runtimes, We have an attachment, in a slot, which belongs to the default skin (not in a placeholder) which is off by default - Slot S attachment A.

We have an animation which we run on the skeleton which keys A on.

All other animations which do not turn the visibility of this slot are fine.

We have one animation (Anim) which keys the visibility of A on, no other keys for A or S exist in this animation.

When This animation end, A is no longer visible. -even though it is never keyed off

The code in AttachmentTimeline.apply(....) enters the if (mixingOut && setupPose) { statement and thus A is
is no longer visible, as slot.data.attachmentName; is null, as it is A is not visible in the setup pose.

With AnimationState in 3.5, when an animation is no longer applied, the skeleton is not left in the state from the last time the animation was applied. Instead, everything mixes back to the setup pose. (There are some exceptions, which are noted in the API docs, eg AnimationState clearTrack.) If there is no mix duration between animations, the change back to the setup pose is instantaneous.

If you want the changes from an animation to be kept, you'll need to either keep applying the animation, or make the changes yourself using code after you apply the AnimationState.

hmm, interesting.

We have an attachment _on animation, that plays on track 1, othing queues after it, and nothing interrupts it. Not looping. (it completes and nothing plays on the track). This animation is one frame long, and sets the visibility of attachment A on, in slot S.

After this animation, the attachment stays on. Should it not turn off when this track mix's to setup?

The current behaviour is that it stays visible until another thing is keyed in another animation (on track 0). If the same attachment (A) is keyed on (even though it is still visible). This attachment will turn off during mixing.

But why does the attachment remain visible when mixing to setup pose if the animation does not key the attachment? An


21 Nov 2016, 09:47


This change, specifically for attachments is a real pain for us now.

Imagine you have multiple characters using the same skeleton and the same skin. some may hold a sword, some may hold a shield, some my hold both ect ect.

Previously We could set a list of animations to play which would decorate the character. and these attachments would stay on until keyed otherwise.

And we key it otherwise a lot, on many different tracks.

Search the API reference for "previous pose" and you'll find a few areas where an animation can leave the skeleton in the pose from when the animation was last applied. Eg, TrackEntry trackEnd explains what happens at the end of a non-looping animation. If this is not what you want, you need to use an empty animation to mix to the setup pose.

It's suboptimal to store game state in the skeleton pose, since this couples the model (the state of your game world) with the view (the stuff that gets displayed). Eg, if you needed to serialize the game state, you'd need to serialize part of the skeleton pose (which attachments are shown). Or, imagine if you hit an enemy and needed to check what attachment is in a slot to know what weapon is equipped so you know how much damage to deal. A better organizational approach would be to store the state in the game's model and push that information to the view so it draws the right things as the model changes.

Mixing back to the setup pose is done for everything: bones, attachments, constraints, etc. The reasoning is not just for model/view separation. Imagine your animation shows some attachments for some visual effects, then it is interrupted in the middle of its playback. In this case you don't want the attachments to stay shown. In other cases, say if you are removing a sword from a sheath, you do want the attachments to stay shown. How can the animation system know what you want?

One solution is to apply animations based on the character's state in the model (idle, walking, running, etc), then apply any pose changes also based on the model (what weapon is equipped, ailment status, etc). Eg, the character is running so you apply running, then the model says he has a sword equipped so you set the sword attachment for the hand slot.

There are a couple approaches to determine which animation to play. Probably the best way is to have states in the model, then you set the current animation based on these states. Super Spineboy does this. This allows the model to be manipulated however is needed without worrying about particular animations, and the view will play the correct animations.

Another way is to consider each animation that is playing as part of the model. This can be tricky, since an animation being applied is really a TrackEntry, which has quite a lot of state.

Events can be used to trigger a change in the model at a particular time in an animation. However, this should be used carefully. Consider an animation that removes a sword from a sheath and the sword isn't visible until halfway through the animation. When does the model consider the sword as equipped? An event could be used which tells the model the sword is now equipped. In this case the model should have an equipSword state, which knows to apply the equipSword animation. Without such a state, if you just played the equipSword animation to change the model using an event, and if you serialized the game state before the event happened, you'd lose the fact that the sword was about to be equipped.

Hopefully by now you've forgotten you even had a question! :clap: This got a bit long, but it's good to consider how your model and view/animations interact. It's very easy to tie them together, especially if you don't have serialization needs, but as the app grows this approach becomes more and more complex. Having your model decoupled from your view can be a pleasure to work with. That said, a scene graph like Unity inherently ties the model to the view (GameObjects) so it is more difficult to organize (I honestly don't know how, most Unity projects are a nightmare :bang: ).

As for solving your particular problem, unless you want to rework how you manage your game state, the easiest thing would be to modify AnimationState so it doesn't reset attachments to the setup pose. To hack her up, in AttachmentTimeline apply change:

if (time < frames[0]) { // Time is before first frame.
    ...
}

To:

if (time < frames[0]) return; // Time is before first frame.

Also, in AnimationState applyMixingFrom, change:

if (timeline instanceof RotateTimeline)

To:

if (timeline instanceof AttachmentTimeline) continue;
if (timeline instanceof RotateTimeline)

I don't know about making this a setting, as it introduces the problem that animations which are interrupted may leave unwanted attachments shown. If by default all slots are reset as they are now and you disable that using a setting, then when changing animations you'd need to call setToSetupPose on the slots you DO want reset.

Mixing back to the setup pose is done for everything: bones, attachments, constraints, etc. The reasoning is not just for model/view separation. Imagine your animation shows some attachments for some visual effects, then it is interrupted in the middle of its playback. In this case you don't want the attachments to stay shown. In other cases, say if you are removing a sword from a sheath, you do want the attachments to stay shown. How can the animation system know what you want?

This is very true. in the past it was possible for our models to get screwed up (in frankly hilarious ways) as the images would persist upon interrupted animations. As a result of this we had/have to key all the images as they are in the setup pose, at the start of all/most animations. This is true for bones too, however it has been done in a slightly overkill manner (imo).

Its great that that is no longer needed, and new animation state changes are great, they have less ambiguous results.

However I feel decoration Animations are somewhat natural to spine's workflow. But you are correct, how can these be segregated from normal attachments, and should they be?

There are a couple approaches to determine which animation ....

Looking back on a project, you can always see ways things should have been done. Unfortunately when you don't know the scope of tomorrow you just have to keep building with the scope of today. In an ideal world we would be using more of spines functionality, i.e. transform constraints,
however in a realistic world of deadlines the motto is more if it aint broke, don't fix it.

Hopefully by now you've forgotten you even had a question

I did :s

As for solving your particular problem, unless you want to rework how you manage your game state,

This worked, although I agree our game state thingy may need to change. In the past we could make the assumptions that sword enemy would have
a sword, always, unless specifically keyed other wise - hence keying the skeletons' state at the start of every animation. say if the sword enemy dropped his sword, we would have a function which would:

void dropsword(){
hassword = false
playdropanimation()
}

and it would be the hassword which would manipulate the state of the enemy.

In my eyes decoration animations should be treated differently to standard attachment animations, but the implementation... well that's for you guys 😛

IIRC, the old animationstate.cs had a uncomment these lines if you don't/do want attachment mixing? or was that event firing

If anything, maybe you could say, "don't reset slots x, y, z". Attachment changes for those slots would not be mixed back to the setup pose. I'm still not quite sold on that being the best solution though.

BinaryCats wrote

21 Nov 2016, 09:47


This change, specifically for attachments is a real pain for us now.

Imagine you have multiple characters using the same skeleton and the same skin. some may hold a sword, some may hold a shield, some my hold both ect ect.

Previously We could set a list of animations to play which would decorate the character. and these attachments would stay on until keyed otherwise.

And we key it otherwise a lot, on many different tracks.

Not to rock the boat, but shouldn't all the attachments for the same skeleton/skin be defined under a main hand / offhand slot and simply turn them on at runtime? Define some scriptable objects that define what an "Orc Warrior" vs "Orc Brute" are for example. I think Nate already hit on most of this, but I tend to agree that the model was really baked into the view a bit much.. not sure how easy you can back out of it at this point.

If it's just equipped items, these should be extremely easy to just swap out with SetAttachment() no?

Majicpanda wrote

But when a decoration attachment has 14 different images for animations, what then? it needs to be keyed through animation. the reason it isn't in a skin is because 50+ skins would be able to use that attachment, creating a place holder for each one, then positioning it is a lot of work, shared assets for skins, in my opinions should be on the default skin.

I'm really quite unsure of how our model and view where coupled. If an entity equipped a weapon we would play the equip weapon animation. That entity then would know it has a weapon and would make decisions accordingly. we certainly where not looking into the skeletons slots and making decisions based of them.

previously hasSword was all that was needed to know if the skeleton had a sword. Now we have to have hasSword and then we need to store extra data about the sword, that has no impact on gameplay nor the decisions the entity makes.

If you have all of the game state in your model, then you should be able to make the view play the appropriate animations with the correct attachments. If hasSword is in your model, each frame you could apply animations, then attach the sword attachment if hasSword is true. Maybe you skip setting it when the current animation is equipSword, allowing the first part of that animation to not have the sword attached.

Previously the sword could be in different positions/slots/ and it would not have effected the state of the game, it was purley visual. but now we need to manage this rather than just play one animation.

I have also found a question mark of how attachments should be handled during the animation, and multiple track. I made a new topic here: 3.5+ Attachments over multiple tracks.

BinaryCats wrote

Previously the sword could be in different positions/slots/ and it would not have effected the state of the game, it was purley visual. but now we need to manage this rather than just play one animation.

All the skeletons and animations are purely visible, yet are driven by the game state. You don't need to store anything extra, you just need to configure the skeleton a little differently since the skeleton is now reset to the setup pose when playing animations for the reasons given above. Things have changed slightly, hopefully for the better.

Nate wrote

You don't need to store anything extra

Say the sword is sheathed, need to loop the sheathed animation, say he then grabs it, need to stop looping the sheathed animation and start playing another one, then at the end of that you then need to start looping the swordInHandAnimation. We now need to manage where the sword is.

Why do you want to use animations to set what attachments are visible? It's simpler to apply the AnimationState, then set what attachments are visible based on your model.

state.apply(skeleton);
if (hasSword && state.GetCurrent(0) != equipSwordAnimation) swordSlot.Attachment = sword;

equipSwordAnimation probably keys the sword attachment visible midway when it comes out of the sheath, that is why we only show the sword if not playing equipSwordAnimation. There is probably an unequipSwordAnimation that keys the attachment visible, then hides it midway when it goes in the sheath, but no special case is needed for that. Code to equip/unequip might look like:

function equipSword () {
   hasSword = true;
   state.SetAnimation(0, equipSwordAnimation, false);
   state.AddAnimation(0, idleAnimation, true, 0);
}
function unequipSword () {
   hasSword = false;
   state.SetAnimation(0, unequipSwordAnimation, false);
   state.AddAnimation(0, idleAnimation, true, 0);
}

I would disagree, as said in another thread. What if a weapon or whatever is over multiple slots? It becomes very cumbersome to decorate a character this way.

What if you use multiple images for this attachment in animations.

Say you character spins around (on the Y axis), you have 8 images of the sword, for different rotations.

We do the code you said above. We always have done. It works, fine. UNLESS you have an animation which keys this slot to a different/the same image.


22 Nov 2016, 16:49


function equipSword () {
   hasSword = true;
   state.SetAnimation(0, equipSwordAnimation, false);
   state.AddAnimation(0, idleAnimation, true, 0);
}
...
equipSword () ;//Sword on
PlayOtherAnim();//Sword on
PlayOtherAnim2();//Sword on
PlayOtherAnim3();//Sword STILL on
...
PlayOtherAnimn()//Sword remains on

However

PlayAnimSpin();//Keys the sword slot attachments on and off
-Blend-//Sword turns off
BinaryCats wrote

What if a weapon or whatever is over multiple slots? It becomes very cumbersome to decorate a character this way.

If xxx weapon is equipped, set attachments on as many slots as you need to equip that weapon. If you need something more complex, like a weapon that is animated, then you probably would want to use an animation to show and animate the weapon.

If you have animations that take over attachment visibility, you could special case them as I showed for equipSwordAnimation. If your spin animation clears the sword attachment, it will come back once spin is complete because you set the sword attachment every frame.

but why should this not be controlled by the artist. setting 20 slots, for each weapon in the game? [/ exestuation].

I'm sorry, I'm lost the equipSwordAnimation is that an animation you are looping every frame? because I need to stop start that loop on different conditions AKA managing the sword's states/

You only set attachments for the equipped weapon/gear. Setting an attachment is just assigning a field, even less if the attachment didn't change.

equipSwordAnimation is the character pulling out the sword. There is no looping, as the equipSword and unequipSword functions above show.

imo, setting slots to specific attachments is very cumbersome. There is no [unity] interface for that. With animations, you can have a list of animations. and more importantly, if the artist wants to change how a weapon looks, an animation turning it on lets him do just that, rather than say "yo, BCats, you need to now set slot blah to foo slot bar x ....." then me have to go and alter the data structure which holds all this information.

Why do these these two cases yield different results?

case1:
Play Animation Idle, Track 0.
Play Animation equipsword Track 1.

Result: sword is equipped (and remains equipped, until case 2 happens)

case2:
Play Animation equipsword Track 0, Queue animation idle (track 0)

result: sword not equipped

It's a different workflow, sure. I think it's expected for there to be application logic to apply animations. I'm not sure it's worth trying to avoid.

You didn't post the set/addAnimation calls, so I don't know if things are looping. I'll just make stuff up and assume nothing loops.
1) When equipSword finishes, the skeleton is left in the state when the animation was last applied. See TrackEntry trackEnd. I suppose we could keep the entry one extra frame and reset the skeleton back to the setup pose in this case. A similar thing happens if you call AnimationState clearTrack, but in that case you told us to get rid of any track entries, so keeping them around for an extra frame to reset the skeleton to the setup pose probably doesn't make sense.
2) When equipSword finishes, it is mixed back to the setup pose.