• RuntimesUnity
  • Wrong scaled animations when using SkeletonGraphic

Hi,
I'm trying to use Spine animations in the UI of a Unity game, using SkeletonGraphic and I simply can't get it to work and fail even to understand what's going wrong.

I read the few threads where similar questions were asked already and, by now, I probably tried every imaginable combination and order for calling Update/UpdateMesh/MatchRectTransformWithBounds and setting sizeDelta etc.

What I'm trying to do is - I have a UI with a panel to show details of a user selected Unit. The panel is inside a bigger prefab and already contains the SkeletonGraphic component to show the unit.
I want the Units to be scaled using the FitInParent mode and to be centered within the panel.

When the user selects a Unit, I lookup the required SkeletonDataAsset and try to show it using the code basically given in 2 other threads in this forum.


var skeleton = AnimationManager.instance.GetSpineSkeleton(unitPrototype.excelId);
if (skeleton != null)
{
    skeletonGraphic.skeletonDataAsset = skeleton;
    skeletonGraphic.startingAnimation = "idle";
    skeletonGraphic.startingLoop = true;
    skeletonGraphic.Initialize(true);
    skeletonGraphic.Update(0f);
    skeletonGraphic.UpdateMesh();
    skeletonGraphic.MatchRectTransformWithBounds();
    
    skeletonGraphic.layoutScaleMode = SkeletonGraphic.LayoutMode.FitInParent;
    skeletonGraphic.rectTransform.anchoredPosition = Vector2.zero;
    skeletonGraphic.rectTransform.sizeDelta = Vector2.zero;
}

What I get, as the result, is a Spine animation that doesn't match the rect and, when I repeat the code, the size of the rendered Spine animation toggles between two wrong sizes. Doesn't matter if I toggle the same SkeletonData or switch to different ones.

I recorded a short gif showing the scene/inspector view - very low fps for a small file size but enough to see the problem. The Spine animation also seems to be displaced wrt to it's own rect transform.

Unity is 2022.3.14f
Spine Unity Runtime 4.1.42

Any idea what's causing this/what I'm doing wrong?

Thanks a lot

Related Discussions
...

It seems like you're encountering issues with scaling and positioning your SkeletonGraphic component within a UI panel in Unity. Based on the provided contexts, here are a few steps and considerations that might help resolve the issue:

  1. Ensure Correct Version Compatibility:

    • Make sure that the versions of the Spine Editor and the spine-unity runtime are compatible. You mentioned using Spine Unity Runtime 4.1.42 with Unity 2022.3.14f, which should be fine, but double-checking never hurts.
  2. Initialization and Update Order:

    • The order of initialization and updates is crucial. Ensure that Initialize, Update, UpdateMesh, and MatchRectTransformWithBounds are called in the correct sequence. Your code seems correct, but let's ensure no steps are missed.
  3. RectTransform Settings:

    • Ensure that the RectTransform settings are correctly applied. Setting anchoredPosition and sizeDelta to zero should center and fit the skeleton within the parent, but double-check the parent’s RectTransform settings as well.
  4. Multiple Canvas Renderers:

    • If you are using multiple blend modes, ensure that Multiple CanvasRenderers is enabled in the SkeletonGraphic component's Advanced settings.
  5. FitInParent Mode:

    • The FitInParent mode should scale the skeleton to fit within the parent’s bounds. Ensure that the parent’s RectTransform is correctly set up to provide the desired bounds.
  6. Example Code:

    • Here is a refined version of your code with additional checks and comments:
var skeleton = AnimationManager.instance.GetSpineSkeleton(unitPrototype.excelId);
if (skeleton != null)
{
    skeletonGraphic.skeletonDataAsset = skeleton;
    skeletonGraphic.startingAnimation = "idle";
    skeletonGraphic.startingLoop = true;
    
    // Initialize the SkeletonGraphic
    skeletonGraphic.Initialize(true);
    
    // Update the SkeletonGraphic to apply changes
    skeletonGraphic.Update(0f);
    skeletonGraphic.UpdateMesh();
    
    // Match RectTransform with bounds
    skeletonGraphic.MatchRectTransformWithBounds();
    
    // Set layout scale mode to FitInParent
    skeletonGraphic.layoutScaleMode = SkeletonGraphic.LayoutMode.FitInParent;
    
    // Center the RectTransform within the parent
    skeletonGraphic.rectTransform.anchoredPosition = Vector2.zero;
    skeletonGraphic.rectTransform.sizeDelta = Vector2.zero;
    
    // Ensure Multiple Canvas Renderers is enabled if using multiple blend modes
    skeletonGraphic.enableMultipleCanvasRenderers = true;
}
  1. Debugging:

    • Add debug logs to check the values of RectTransform properties before and after setting them to ensure they are being applied correctly.
    • Verify that the SkeletonDataAsset is correctly assigned and initialized.
  2. GIF Analysis:

    • From the GIF, it seems like the animation is not fitting correctly within the bounds. Ensure that the parent panel’s RectTransform is correctly sized and positioned.

If the issue persists, consider creating a minimal Unity project that reproduces the problem and testing it in isolation to rule out any project-specific settings or conflicts.

@Nelvin Sorry to hear you're having troubles! Does your SkeletonGraphic component have Advanced - Multiple CanvasRenderers enabled, and does the issue still occur if you disable this setting?

  • Nelvin đã trả lời bài viết này.
  • Nelvin đã thích điều này.

    @Nelvin Sorry, I noticed that you're setting Multiple CanvasRenderers via code.

    I just tested your code, it's indeed a bug with the spine-unity runtime (also present on the 4.2 branch).
    A quick fix is to set the layoutScaleMode to LayoutScaleMode.None before the mesh is first updated, as the MatchRectTransformWithBounds method currently takes the scaled mesh after layout scale mode has enlarged it.

    I've created an issue ticket here:
    EsotericSoftware/spine-runtimes2577
    Thanks for reporting!

    Until a bugfix is released, the quick-fix code would be as follows:

    skeletonGraphic.layoutScaleMode = SkeletonGraphic.LayoutMode.None; // add this line
    skeletonGraphic.Initialize(true);
    
    //skeletonGraphic.Update(0f);  // you can remove this call
    //skeletonGraphic.UpdateMesh(); // you can remove this call as well
    skeletonGraphic.MatchRectTransformWithBounds();
    
    skeletonGraphic.layoutScaleMode = SkeletonGraphic.LayoutMode.FitInParent;

    Note that you can remove the calls to Update() and UpdateMesh() as they are also called by MatchRectTransformWithBounds (see the code here).

      Harald
      Thanks for your fast reply - it's disabled, for the sake of completeness I enabled it, but the result was just an error.

      ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.
      Parameter name: index
      System.Collections.Generic.List`1[T].get_Item (System.Int32 index) (at <a3b02d6f9b494355b946095ea1f25c54>:0)
      Spine.Unity.SkeletonGraphic.PrepareRendererGameObjects (Spine.Unity.SkeletonRendererInstruction currentInstructions, System.Boolean isInRebuild) (at ./Library/PackageCache/com.esotericsoftware.spine.spine-unity@879c7adb37/Runtime/spine-unity/Components/SkeletonGraphic.cs:1049)
      Spine.Unity.SkeletonGraphic.PrepareInstructionsAndRenderers (System.Boolean isInRebuild) (at ./Library/PackageCache/com.esotericsoftware.spine.spine-unity@879c7adb37/Runtime/spine-unity/Components/SkeletonGraphic.cs:736)
      Spine.Unity.SkeletonGraphic.UpdateMesh () (at ./Library/PackageCache/com.esotericsoftware.spine.spine-unity@879c7adb37/Runtime/spine-unity/Components/SkeletonGraphic.cs:743)
      ArmyBuildingPopup.SelectUnitToBuy (Unit unitPrototype) (at Assets/Scripts/UI/Menus/Army Management Elements/ArmyBuildingPopup.cs:120)
      EventChannels.SelectUnitToBuy (Unit unit) (at Assets/Scripts/SpellSystem/SpellManager.cs:22)
      ArmyManagementScreen.ShowBuildingPopup (ArmyBuildingType buildingType, UnityEngine.UI.Image imgLevel1, UnityEngine.UI.Image imgLevel2, UnityEngine.UI.Image imgLevel3) (at Assets/Scripts/UI/Menus/ArmyManagementScreen.cs:981)
      ArmyBuildingButton.SelectCategory () (at Assets/Scripts/UI/Menus/Army Management Elements/ArmyBuildingButton.cs:107)
      ArmyManagementScreen.Update () (at Assets/Scripts/UI/Menus/ArmyManagementScreen.cs:229)
      • Harald đã trả lời bài viết này.

        Harald
        Sorry for my late reply but my ISP is having issues since Friday.
        Thanks a lot for your help - strangely this helps in my preview panel where the currently selected unit is shown but not when I use the exact same code (using the same method where I initialize the SkeletonGraphic, set the scaling mode etc.) for the list of selectable units. For these, my Spine animations are scaled down to a tiny size rather than filling the available rect.
        In my quest to find the issue or at least a workaround, I eventually tried to just DestroyImmediate the SkeletonGraphic component and add a new one. So far, this seems to work.

        I've attached a screenshot and it seems the rectTransform is correct but the scaling of the mesh is wrong.

        What I noticed is, if I do not set the sizeDelta to zero, the visual scaling is correct but only because the rectTransform is huge and, as a result, the selected unit is way to big.

        Finally, if I call MatchRectTransformWithBounds before and after setting layoutScaleMode to FitInParent, it works for in both cases.

        Any further idea what may go wrong when reusing the existing one?

        I can use either workaround but I'd feel more comfortable to know if there might be an issue on my side or if this is caused by the issue you tracked, so will eventually be fixed.

        Thanks a lot

        • Harald đã trả lời bài viết này.

          Harald @Nelvin Sorry, I noticed that you're setting Multiple CanvasRenderers via code.

          I just noticed it was Spinebot who suggested the setting, not your actual code.

          Nelvin Thanks for your fast reply - it's disabled, for the sake of completeness I enabled it, but the result was just an error.

          I could not yet reproduce such an error message when enabling Multiple CanvasRenderers. How did you enable this setting? By enabling it in the Inspector, or via code? If via code, where in relation to the other API calls did you place the call?

          • Nelvin đã thích điều này.

          Nelvin What I noticed is, if I do not set the sizeDelta to zero, the visual scaling is correct but only because the rectTransform is huge and, as a result, the selected unit is way to big.

          Finally, if I call MatchRectTransformWithBounds before and after setting layoutScaleMode to FitInParent, it works for in both cases.

          Any further idea what may go wrong when reusing the existing one?

          I can use either workaround but I'd feel more comfortable to know if there might be an issue on my side or if this is caused by the issue you tracked, so will eventually be fixed.

          Thanks for sharing your investigations. We will publish a proper bugfix, I was just not fast enough on Friday evening with finding the proper solution.

          • Nelvin đã thích điều này.

          @Nelvin We have just released a bugfix for the issue on the 4.2 branch.
          A new spine-unity 4.2 unitypackage is available for download here as usual:
          https://esotericsoftware.com/spine-unity-download
          Please let us know whether this fixes the issue on your end as well. Thanks for reporting!

          • Nelvin đã trả lời bài viết này.
          • Nelvin đã thích điều này.

            Harald I'm currently bound to 4.1 - is it possible to add the changes to the 4.1 branch too? That would be great.

            Thanks a lot.

            @Nelvin Sorry to say that such a commit is slightly too risky, it might break existing 4.1 projects.

            Nevertheless, you should be able to integrate the changes of the following commit quite easily into your local spine-unity 4.1 runtime installation:
            EsotericSoftware/spine-runtimesb1fe837

            • Nelvin đã trả lời bài viết này.
            • Nelvin đã thích điều này.

              Harald No problem and very understandable - I'll integrate the changes locally then.

              • Harald đã thích điều này.

              Glad to hear, thanks for your understanding.