• Unity
  • SetSkin during runtime - flickering textures

Hi,

I have a game where I'm changing spine animation skins at runtime using SetSkin().

I have 3 skins which are basically different features/colours/animations of a cartoon face. The faces all appear in a grid, amongst other items. After a while the face will disappear from the grid, but can reappear again later (I'm object pooling them with a pool of about 20).

To begin with SetSkin() is working correctly and the faces change skin. However after a while of using SetSkin things start to deteriorate and I start seeing flashes of old skins/animations, or parts of the skin go missing. It feels like it happens randomly, and it can start happening at any time (but it's always after calling SetSkin a few times).

My guess is the object pooled faces are being reused and previous skins/animations are loitering and effecting things.

When I change skin I'm doing this -

_skeletonAnimation.skeleton.SetSkin(skin); // 1. Set your skin.
_skeletonAnimation.skeleton.SetSlotsToSetupPose(); // 2. Make sure it refreshes.
_skeletonAnimation.AnimationState.Apply(_skeletonAnimation.Skeleton); // 3. Make sure the attachments from your currently playing animation are applied.

If I don't use lines 2 and 3 above things are worse, so having these lines definitely helps but doesn't stop the issue.

Also beneficial is using 'clear state on disable' in the Unity editor. This seems to prevent things going wrong a bit longer.

I've tried using this but it doesn't help -

_skeletonAnimation.AnimationState.SetEmptyAnimations(0);

Any ideas would be appreciated. Ideally I would just like a way of completely resetting the skin in the OnEnable() method (when the object is released from the pool it is set to active and triggers this).

Thanks!

Related Discussions
...
  • Изменено

"clear state on disable" is precisely for use with object pools, so that the state from a previous "instance" does not get inherited.
However, currently, the clearing the state does not include clearing the skin assignment. This decision was based on the assumption that skin is not quite state.
You can change that part of the code here: spine-runtimes/SkeletonRenderer.cs at 3.6
The new method would look like this:

csharp
      public virtual void ClearState () {
         meshFilter.sharedMesh = null;
         currentInstructions.Clear();
         if (skeleton != null) {
            skeleton.Skin = null; // also clear the skin value.
            skeleton.SetToSetupPose();
         }            
}

In any case, your "flicker" might just be an execution order thing, where the previous skin was used and rendered before you could properly initialize your new instance you obtained from the pool.

If you want to force a rebuild of the visible mesh after changing the skin, you need to call skeletonAnimation.LateUpdate();

Beyond that, I can only guess. If you have some video of it happening or something, that could help us debug further.

9 дней спустя

Thanks for the response, unfortunately none of the suggestions worked - BUT - I did end up fixing it by repackaging everything so it only used 1 texture png.