- Bearbeitet
Resetting attachments to default via code?
What I want to achieve is resetting all attachment images to their default whenever a new animation starts. Because I don't key all of them in all animations as it would be inefficient, when transitioning between two animations, the target animation will use the wrong attachment images (for example, the body would be turned, when it's supposed to be straight).
A solution i've found is to make an animation called "resetAttachments" or so, and every time I transition to a new animation, I load that animation into the state. The animation contains keys for all attachments in their default state. It seems kind of sloppy, and I'd have to make that same animation for all the characters, and whenever I add a new attachment image to the skeleton.
Is there a way to reset all attachment images via code to their default (as they appear in the pose editor in Spine)? Maybe a way to only change those that aren't in the default state already.
This is what skeleton.SetSlotsToSetupPose() does.
It also resets draw order. But it sounds like that would work fine in your case.
You could also use skeleton.SetToSetupPose()
to exactly match how the editor doesn't inherit poses between animations.
If, for some reason, you just want to reset attachments and don't want it to reset the draw order, you may have to set up your own method that does:
public static void SetSlotsToSetupPoseButNotDrawOrder (Skeleton skeleton) {
var slots = skeleton.slots;
for (int i = 0, n = slots.Count; i < n; i++)
slots.Items[i].SetToSetupPose(i); // this also resets slot colors
}
Nice, thanks for the in-depth answer c:
26 Mar 2016, 01:22
I'm having an issue where attachments are still being changed from the old animation when transitioning into a new animation.
It makes sense, but I'm wondering if there's a way to only to change attachment images from the new animation? Didn't realise this is the problem I was having.
For example, my character is running, and transitioning into idle. I change the body image in the very start of idle, but while transitioning, the run animation changes some attachments, and the result is the idle animation mixed with some of the run animation. I'd want it to only count the attachment changes from idle.
Ah. There's a number of possible fixes for that.
If you are using mixing.
One I can think of is to comment out this line from Animation.cs
(if you want the next animation to reliably override attachments from the previous animation)
https://github.com/EsotericSoftware/spine-runtimes/blob/master/spine-csharp/src/Animation.cs#L451
That step makes attachments be applied every frame instead of only when time passes over the key (like events).
And then probably add this in its place
const float alphaThreshold = 0.5f; // don't set the attachment below 0.5 alpha.
if (alpha < alphaThreshold) return;
That seems to work! c: Thank you.
Now whenever I update the runtime in the future, I'd have to comment out the line every time I imagine. Are there any plans to maybe add a setting for it in unity somehow? To me it seems much more desireable when mixing between animations, but I guess it's less optimized.
Anyway, thanks for the help c:
There's an update to AnimationState and Animation systems coming to all runtimes and that's part of it.
But for the next few updates until that one gets applied, yeah, you have to do that.
I'm also having this problem, and SetSlotsToSetupPose() does this trick before SetAnimation(). However, what should I do if I want to queue up an animation using AddAnimation()?
jdbones If you want to perform the same process at the start of any animation, you could register it to the AnimationState.Start
event. For more information about AnimationState events, please see the spine-unity runtime documentation: http://esotericsoftware.com/spine-unity#Processing-AnimationState-Events
Misaki Thank you so much!
I ran into another issue with this though. If I call SetSlotsToSetupPose() before playing an animation, it sometimes very briefly flashes the setup pose before playing the animation. It seems to be only a single frame, but if I pause Unity and try to advance frames, it never happens. I can see it best by recording the screen and stepping through a video.
Here's what I'm doing:
_skeletonAnimation.Skeleton.SetSlotsToSetupPose();
AnimationState.SetAnimation(0, animationName, loop);
Am I doing something incorrectly? Is there a way to get it not to flash that setup pose?
SetSlotsToSetupPose
changes the skeleton pose, but setting an animation on AnimationState does not, not until the AnimationState is applied to the skeleton. You can do that:
AnimationState.Apply(_skeletonAnimation.Skeleton);
That happens for you normally, but if you change the animation afterward within a single game frame, you won't see it applied until the next frame.
@jdbones Please note that with the spine-unity runtime, animations are updated and applied to the skeleton state in SkeletonAnimation.Update()
, and the MeshRenderer
mesh is filled based on the skeleton state in LateUpdate
. See the documentation here.
In general, if you change animation state or skeleton state, it depends on from where you are calling your code in the update cycle, due to Unity's script execution order your script code might execute too late (having an effect one frame too late) or too early (having no effect).
As a consequence, it is recommended to either issue a single call following your changes like skeletonAnimation.AnimationState.Apply(skeletonAnimation.Skeleton);
as Nate mentioned above, or if you need to apply something each frame (e.g. overriding bone position or manually changing materials), use one of the provided callback methods described in SkeletonAnimation Update Callbacks here.