• RuntimesUnity
  • Swapping atlases based on screen resolution

JDBB When scaling an 8k image down to switch sizes I end up with a bad looking sprite, so I have come to the conclusion that I need to supply my own (manually authored) set of sprites at different scales. My sprites are made entirely using vector software (illustrator at the moment) so I have the option to just export sprites at different scales. When I do this I get much better results than letting unity auto scale them down (as expected).

Thanks for the clarification, this makes sense, automatic downsampling (via Unity's mipmap generation as well as via Spine Atlas Export Scale e.g. 0.5 or 0.25) will be inferior to that.

JDBB I have seen that I can use the spine texture packer to make a standalone atlas using my lower resolution sprites but I don't know if I could just swap the textures out as I don't think there is any guarantee that the
sprites will be packed into the same place in all the different atlases.

There is indeed no guarantee if you pack twice with different settings or resolutions.

JDBB I'm not sure if it is possible to swap the atlas itself out?

Yes, this is possible and perfectly valid. The AtlasAsset (and the referenced atlas.txt file) contains all the necessary information.

JDBB I want to be able to supply multiple sets of sprites that have been exported from illustrator at different scales.

By that I assume you mean that you want to author the attachment images for the Spine project in different resolutions, and then pack them to different sets of atlases, not sharing the same layout (see above).

JDBB I want to not have to load one set of textures then only after that load the correct set of textures as that would increase loading time.

If you have a different AtlasAsset for each resolution with different atlas layout, you unfortunately can't use the Spine Addressables Extension on-demand loading module mentioned earlier, as this only replaces textures at materials and does not (yet) support different atlas layouts (i.e. does not support swapping out the atlas asset with a different one).

I assume this is not an option, but you could load a low-resolution atlas first (with little overhead) and then swap out the low-resolution atlas with the desired target resolution atlas.

If you need to avoid loading a low-resolution placeholder atlas asset first, you could programmatically at runtime load the SpineAtlasAsset first and then construct the SkeletonDataAsset, as described here:
https://esotericsoftware.com/spine-unity-main-components#Advanced-Instantiation-at-Runtime

Alternatively, you could write your own AttachmentLoader to customize loading, as described recently on this forum thread:
https://esotericsoftware.com/forum/d/26266-how-to-export-texture-just-for-one-skin-with-linked-mesh

JDBB Ideally I would also like to be able to not include the higher res textures when I build for the switch (not essential).

You could either always include just the lowest-resolution atlas, or download all atlas assets via addressables on-demand.

JDBB Ideally I would be able to swap the texture scale after the scene/prefab is already on screen (so that the game can adjust when the resolution changes, not essential).

You can swap out the atlas assets by assigning a different atlas asset at SkeletonDataAsset.atlasAssets and then call skeletonDataAsset.Clear() to clear the common loaded SkeletonData. Then at all already loaded SkeletonAnimation objects you would need to call skeletonAnimation.Initialize(true); to reload and re-assign the proper skeleton data.

In general there are multiple ways to achieve your goal. I hope this hasn't raised more questions than it has answered. 🙂

Related Discussions
...

Thanks, I will work on testing some of this later when I am able.

When you turn an attachment into a mesh, where is this mesh vertex data stored?

If I were to export a set of lower resolution sprites into an atlas using the spine texture packer, then manually load the low res atlas in unity and assign it to the skeleton data (that was exported with the high res atlas), would this break any animations that rely on having mesh attachments?

  • Harald がこの投稿に返信しました。

    JDBB When you turn an attachment into a mesh, where is this mesh vertex data stored?

    What do you mean by "when you turn an attachment into a mesh", do you mean in the Spine Editor?

    If you want to know whether mesh attachments directly store atlas texture coordinates: no, they store coords relative to the atlas region boundaries, and the atlas regions are defined by the atlas. Thus the atlas layout can be different and mesh attachments still work fine.

    JDBB If I were to export a set of lower resolution sprites into an atlas using the spine texture packer, then manually load the low res atlas in unity and assign it to the skeleton data (that was exported with the high res atlas), would this break any animations that rely on having mesh attachments?

    It does not break anything.

    Hey, that answers my question, thanks.

    I thought that I had it working by simply setting the 'atlas assets array' to be empty in the 'skeleton data asset'. This allowed the 'skeleton animation' object in my scene to load up fine with no atlases. Then I could load the desired atlas using addressables and assign it as you explained before.

    This worked fine in the editor but failed in a build with the error: "Error reading skeleton JSON file for SkeletonData asset: skeleton_SkeletonData"

    In the inspector for the 'skeleton data asset' it says "AtlasAsset array is empty. Skeleton's attachments will load without being mapped to images.". Which sounds like the exact behavior that I want and also sounds like having an empty atlas array is supported.

    Does this suggest that the error that I'm getting in my build is actually a bug?

    I have also seen references to 'RegionlessAttachmentLoader' in the spine source which also may suggest that having no atlas is supposed to work.

    I tried to look into making a custom attachment loader but I couldn't see how to make the 'skeleton animation' object in my scene use my custom loader.

    Sorry for so many questions, hopefully nearly there. Thanks again for all the help.

    I have done some more work on this and everything seems to be working perfectly in both the build and in the editor, apart from the error that gets thrown when running the build (mentioned above).

    As soon as I have a skeleton data asset with an empty atlas list then I get the error in the build.

    I could just ignore the error but I would much rather fix it.

    Glad to hear you've got a working solution already! Sorry for the troubles with the error message, we will check whether we can remove it safely. I'll get back to you here on the forum once we have a fix ready.

    • JDBB が「いいね」しました。

    @JDBB Unfortunately we could not reproduce the issue, we received no error message when entering play mode or building with a scene which uses a skeleton with the SkeletonDataAsset's Atlas Assets size set to 0.

    Which exact version of the spine-unity runtime (name of the unitypackage, also listed in Assets/Spine/version.txt or in the Package Manager) are you using?

    The version of the Unity runtime is: 4.2.67
    The C Sharp runtime is: 4.2.23
    I am using Unity version: 2023.2.20

    I did have the addressables and on demand loading packages installed at one point but have since removed them from the project.

    @Harald

    I have just made a fresh project to test on and I am still seeing the error.

    I can send you the project if you would like.

    Steps that I took:

    1. Made a new universal 2D project in Unity 2023.2.20
    2. Installed the two spine packages via the package manager
    3. Dragged a spine export into unity, this generated the skeleton data asset
    4. Dragged the skeleton data asset into the starting scene and let it generate the skeleton animation game object
    5. In the inspector for the skeleton data asset I set the atlas assets list count to be 0
    6. Built the project

    Hopefully I didn't miss anything.

    In case it helps the full error is:

    Error reading skeleton JSON file for SkeletonData asset: skeleton_SkeletonData
    Error reading attachment: God_Ray_0, skin: default
    at Spine.SkeletonJson.ReadSkeletonData (System.IO.TextReader reader) [0x013d8] in .\Library\PackageCache\com.esotericsoftware.spine.spine-csharp@568e5ef049\SkeletonJson.cs:369
    at Spine.Unity.SkeletonDataAsset.ReadSkeletonData (System.String text, Spine.AttachmentLoader attachmentLoader, System.Single scale) [0x00017] in .\Library\PackageCache\com.esotericsoftware.spine.spine-unity@568e5ef049\Runtime\spine-unity\Asset Types\SkeletonDataAsset.cs:295
    at Spine.Unity.SkeletonDataAsset.GetSkeletonData (System.Boolean quiet) [0x000c4] in .\Library\PackageCache\com.esotericsoftware.spine.spine-unity@568e5ef049\Runtime\spine-unity\Asset Types\SkeletonDataAsset.cs:194
    UnityEngine.Debug:ExtractStackTraceNoAlloc (byte*,int,string)
    UnityEngine.StackTraceUtility:ExtractStackTrace () (at C:/build/output/unity/unity/Runtime/Export/Scripting/StackTrace.cs:37)
    UnityEngine.DebugLogHandler:Internal_Log (UnityEngine.LogType,UnityEngine.LogOption,string,UnityEngine.Object)
    UnityEngine.DebugLogHandler:LogFormat (UnityEngine.LogType,UnityEngine.Object,string,object[])
    UnityEngine.Logger:Log (UnityEngine.LogType,object,UnityEngine.Object)
    UnityEngine.Debug:LogError (object,UnityEngine.Object)
    Spine.Unity.SkeletonDataAsset:GetSkeletonData (bool) (at ./Library/PackageCache/com.esotericsoftware.spine.spine-unity@568e5ef049/Runtime/spine-unity/Asset Types/SkeletonDataAsset.cs:197)
    Spine.Unity.SkeletonRenderer:Initialize (bool,bool) (at ./Library/PackageCache/com.esotericsoftware.spine.spine-unity@568e5ef049/Runtime/spine-unity/Components/SkeletonRenderer.cs:476)
    Spine.Unity.SkeletonAnimation:Initialize (bool,bool) (at ./Library/PackageCache/com.esotericsoftware.spine.spine-unity@568e5ef049/Runtime/spine-unity/Components/SkeletonAnimation.cs:189)
    Spine.Unity.SkeletonRenderer:Awake () (at ./Library/PackageCache/com.esotericsoftware.spine.spine-unity@568e5ef049/Runtime/spine-unity/Components/SkeletonRenderer.cs:408)
    (Filename: ./Library/PackageCache/com.esotericsoftware.spine.spine-unity@568e5ef049/Runtime/spine-unity/Asset Types/SkeletonDataAsset.cs Line: 197)

    I just realised that there may be a misunderstanding.

    The error shows when I run the build and the first scene loads, not when entering play mode in the editor or when I build the build.

    • Harald がこの投稿に返信しました。

      JDBB I just realised that there may be a misunderstanding.

      The error shows when I run the build and the first scene loads, not when entering play mode in the editor or when I build the build.

      Thanks for the clarification, I have indeed overlooked this important part!
      (Your reproduction steps list above is also missing "7. Run the built executable and observe the error message in the console" 😉 ).

      We've just improved the error message that is given in this case:

      Shader "Spine/Special/HiddenPass" not found while loading SkeletonDataAsset" with 0 Atlas Assets. Please add this shader to Project Settings - Graphics - Always Included Shaders, or make sure your SkeletonDataAssets all have an AtlasAsset assigned.

      So the issue was just the missing shader which was not found in the built executable which is found in the Unity Editor in play mode.

      A new spine-unity 4.2 unitypackage is available for download:
      https://esotericsoftware.com/spine-unity-download

      Issue ticket URL for later reference:
      EsotericSoftware/spine-runtimes2544

      Yeah, my bad for sure. I should have been more clear. I did try editing my post to add the 7th step after I realised my mistake but it said that I don't have permissions.

      Thanks, I will try adding the shader as suggested.

      • Harald がこの投稿に返信しました。

        Looks like it is working great. Thanks so much for the help 💓

        JDBB No need to apologize, I just found it a funny coincidence 🙂. It's very easy to forget to mention steps, especially those one considers trivial or "clear anyway".

        Very glad to hear it's working well for you now, thanks for getting back to us!