• Unity
  • Redundant UpdateMesh when setting "color" of SkeletonGraphic

Related Discussions
...

Hello ! ๐Ÿ™‚

I have a performance issue when trying to fade out a SkeletonGraphic via code.
To do that, I am using the SkeletonGraphic.color property, inherited from UnityEngine.UI.Graphic.color, and modify its alpha.
My first question is : is it the correct way to do it ? (or should I use a CanvasGroup on top, or another method...)

When profiling, I was surprised by the long time processing Canvas.SendWillRenderCanvases, in particular, CanvasUpdate.PreRender.

After debugging, I eventually understood that :

  1. Setting the color property marks the vertices of the Graphic component as dirty :
    public virtual Color color { get { return m_Color; } set { if (SetPropertyUtility.SetColor(ref m_Color, value)) SetVerticesDirty(); } } // from UnityEngine.UI.Graphic.cs
  1. The dirty SkeletonGraphic will be rebuilt during the Canvas Update (cf. "SpineCanvasRebuild" screenshot)

  2. When rebuilding, the SkeletonGraphic will (re)Update its mesh.

    // From SkeletonGraphic.cs
    public override void Rebuild (CanvasUpdate update) {
       base.Rebuild(update);
       if (canvasRenderer.cull) return;
       if (update == CanvasUpdate.PreRender) UpdateMesh(keepRendererCount: true);
       if (allowMultipleCanvasRenderers) canvasRenderer.Clear();
    }

For my use case, this is redundant : the mesh is already updated in SkeletonGraphic.LateUpdate(), I don't want to reupdate it in the same frame as it was already quite expensive ^^"

So I tried setting the color not via the color property, but directly in the skeleton using skeleton.A or skeleton.SetColor().

Unfortunately, SkeletonGraphic eventually uses this Graphic.color property I'm dreading :

public void UpdateMesh (bool keepRendererCount = false) {
   if (!this.IsValid) return;

   // !!!
   skeleton.SetColor(this.color); // !!! The culprit !!!
   // !!!

   var currentInstructions = this.currentInstructions;
   if (!this.allowMultipleCanvasRenderers) {
      UpdateMeshSingleCanvasRenderer();
   } else {
      UpdateMeshMultipleCanvasRenderers(currentInstructions, keepRendererCount);
   }

   if (OnMeshAndMaterialsUpdated != null)
      OnMeshAndMaterialsUpdated(this);
}

Do you have any recommendation ? How can I achieve my effect, possibly without modifying the Spine Unity runtime ?

Thanks in advance ๐Ÿ™‚


One way I see to prevent this would be to temporarily limit the updateMode to "OnlyAnimationStatus", while I do my alpha fading.

But I'd be happy to hear other solutions ๐Ÿ™‚

Thanks very much for reporting and sorry for the troubles! Unfortunately a proper clean fix turns out to be a bit more complex as the devil lies in the details (allowing multiple submeshes).

We have created an issue ticket here:
https://github.com/EsotericSoftware/spine-runtimes/issues/2049
We will let you know as soon as we have a bugfix to offer.


This issue has just been fixed on the 4.1-beta branch, the SkeletonGraphic update code has been re-arranged to prevent these redundant updates.

A new spine-unity 4.1-beta unitypackage is available for download here as usual:
Spine Unity Download
Please let us know if this resolves the issue on your side as well. Thanks again for reporting!

6 days later

The fix looks cool, thanks ! ๐Ÿ™‚

If we cannot switch to the 4.1 runtime for X reason before we have to release, I think we will just set the UpdateMode to something different than FullUpdate.
This should prevent the double mesh update during fade out.

Sorry to hear that you don't immediately benefit from it, we hope that it will make things easier for you and your team in the future. Thanks for reporting and for getting back to us! ๐Ÿ™‚