• Unity
  • [Unity3D] RegionAttachment Override Delay

Related Discussions
...

We are working on rogue-like and have implemented custom player gear using RegionAttachment swapping with something similiar to this:

Spine.RegionAttachment regionAttachment = loader.NewRegionAttachment(null, "Hair", "hair_001");
if(regionAttachment != null)
{
   regionAttachment.Width = regionAttachment.RegionOriginalWidth;
   regionAttachment.Height = regionAttachment.RegionOriginalHeight;         
   // ...
   regionAttachment.UpdateOffset();
   
   slot.Attachment = regionAttachment;
}

However, there is a noticeable delay until the RegionAttachment shows up. It seems as though it waits until the next keyframe comes around for the attachment.

Is there a way to manually force the SkeletonRenderer to update it's RegionAttachment's?

Assigning an Attachment to a Slot should be instant. Could it be your AttachmentLoader that's taking a while to get the image?

No sorry Mitch, I believe it has something do with the attachment keyframe.

I just tried adding a keyframe every frame and then tested the swapping of hair: it happens almost immediately now. Everything else took a second to catch up. Which I'm assuming until the animation loops and it hits the first keyframe for the attachment.

Any suggestions?

Are you updating the slots? im pretty sure the attachment timeline does this, aand that's why it will update on the apply of the attachment time line


hmm, doesn't seem like it updates from the timeline, my bad.

it will update when you do these functions in your update loop:

	`spSkeleton_update( m_pSkeleton, timeNow );`
	`spAnimationState_update( m_pAnimationState, m_Time );`
	`spAnimationState_apply( m_pAnimationState, m_pSkeleton );`
       `spSkeleton_updateWorldTransform( m_pSkeleton );`

I think you need to do spSkeleton_update when you replace the attachment (I haven't read what the function does, but this feels right)


umm, BC what are you talking about, that's deffinatly not the function.

These functions all happen in the SkeletonAnimator that Mitch created? I don't think that is the solution.

Checkout the Chimera and CustomSkin code - they kinda cover this stuff. As far as I can tell they both still work correctly.

Could this be a problem with script execution order in Unity?

I had an issue where I was trying to rotate a bone to aim towards a touch location and then proceed to fire a weapon. By default, scripts are loaded at random and then executed in said random order. In my case, an issue would arise where the skeleton update would get called before my input event that triggered a bone rotation and weapon fire.

Even though in my code it went something like:

shoulderBone.transform.localRotation = aimRotation;
equippedWeapon.Fire();

Because skeleton update was called first, what really happened was the above code would execute on frame 12 for example, and the skeleton wouldn't update until frame 13 since it's update was already called in frame 12 before I told it to change any rotations.

Perhaps something like this is happening to you? The attachments are updating, but then your event that triggers an attachment change is happening after they already updated for that frame. Perhaps try to use the Script Execution Order and have your input events happen before default time so that way they occur before the skeleton updates.

This at least fixed my issued to get the skeleton to update after I did any runtime modifications. Hopefully it's a similar issue for you.

Mitch wrote

Checkout the Chimera and CustomSkin code - they kinda cover this stuff. As far as I can tell they both still work correctly.

This reminds me... I have done this before

You could you just not do spSlot_setAttachment.

Something as in this thread:
Skinning

only not take the attachment from the skin, instead from the loader?

This is what we are doing. We are setting a slot's attachment based on a loader. We have a bunch of atlases loaded into an array and we iterate through them until we find the attachment we are looking for by string name. We then create an attachment from that load and set it for the slot. This all works fine and we have a customizable hero. The problem is that there is a noticeable delay. My second post (where I set the redundant keyframes every frame) shows that there is something happening in the runtime that isn't immediately updating the mesh in Unity, even though setting an attachment should happen instantly. We are not seeing the mesh update until another slot attachment keyframe gets triggered.

I am not sure what is happening then? Maybe it doesn't detect the slot has changed? maybe its a unity only thing?

We've narrowed down the problem based on this post by Nate:

Skinning
"We used to do a lookup every frame for an AttachmentTimeline, but it proved to be a performance bottleneck for animations with many of those timelines....We changed AttachmentTimeline to only lookup and set the attachment when the frame with the key is crossed."

In the Animation.cs file for the AttachmentTimeline class:

public void Apply (Skeleton skeleton, float lastTime, float time, ExposedList<Event> firedEvents, float alpha) {
   float[] frames = this.frames;
   if (time < frames[0]) {
      if (lastTime > time) Apply(skeleton, lastTime, int.MaxValue, null, 0);
      return;
   } else if (lastTime > time) //
      lastTime = -1;

   int frameIndex = (time >= frames[frames.Length - 1] ? frames.Length : Animation.binarySearch(frames, time)) - 1;
   if (frames[frameIndex] < lastTime) return;

   String attachmentName = attachmentNames[frameIndex];
   skeleton.slots.Items[slotIndex].Attachment =
       attachmentName == null ? null : skeleton.GetAttachment(slotIndex, attachmentName);
}

When we change it to:

public void Apply (Skeleton skeleton, float lastTime, float time, ExposedList<Event> firedEvents, float alpha)
{
   String attachmentName = attachmentNames[0];
   skeleton.slots.Items[slotIndex].Attachment = (attachmentName == null ? null : skeleton.GetAttachment(slotIndex, attachmentName));
}

The slot attachment updates immediately! Obviously this re-introduces the bottleneck Nate was talking about and we need to find a good way handle this. We will continue on and post a solution soon hopefully.

15 days later

Sorry you ran into that. We will try and implement a solution when we update the runtimes to work with v3.

Nate wrote

Sorry you ran into that. We will try and implement a solution when we update the runtimes to work with v3.

When are the v3 runtimes supposed to be out? We're probably about a month or two out from an early-access release of our game so wondering if we need to find a way to patch it ourselves or if runtimes will updated by then?

It's hard to say. Even once v3 is ready, the runtimes need to be updated. spine-unity has a bit of code that needs fixing to move to the v3 way of scaling. I'd like it to be out in a month or so, but there are too many variables to make for an accurate date.

10 months later

So is there a decent way to handle this on Spine V2? V3 broke all of our animations, so we are stuck using an older runtime and editor (2.1.27 I believe). Maybe Pharan has an idea?