Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Bug SpriteAtlas atlasRequested only called first time a scene is loaded

Discussion in 'Addressables' started by Mitjans_AmuseNetwork, Jun 29, 2020.

Thread Status:
Not open for further replies.
  1. Mitjans_AmuseNetwork

    Mitjans_AmuseNetwork

    Joined:
    Aug 3, 2017
    Posts:
    24
    Hello,

    I have some spriteAtlases placed in different addressable groups. I also have addressable scenes that include the sprites from the atlas. The atlases have the NOT "include on build" in the inspector and, in the addressable groups, I only include the atlases and not the sprites to avoid duplicates. To load the sprites I use the following:

    Code (CSharp):
    1. public static void SpriteAtlasManager_atlasRequested(string atlasTag, Action<SpriteAtlas> callback)
    2. {
    3.         string address = currentAppName + "/Atlas/" + atlasTag + ".spriteatlas";
    4.         var op = Addressables.LoadAssetAsync<SpriteAtlas>(address);
    5.         op.Completed += operation =>
    6.         {
    7.             if (operation.Result != null)
    8.             {
    9.                 callback.Invoke(operation.Result);
    10.             }
    11.             else
    12.             {
    13.                 Debug.LogError("Atlas: Atlas with tag " + atlasTag + " not found in addressables. Remember to place or atlases under folder [APP-CODE]/Atlas/[atlas].spriteatlas");
    14.             }
    15.             Instance.m_loadedAtlases.Add(operation.Result);
    16.             //Addressables.Release(operation);
    17.         };
    18. }
    and then add the callback:

    Code (CSharp):
    1.                 SpriteAtlasManager.atlasRequested += SpriteAtlasManager_atlasRequested;
    2.  
    The first time I load I scene, everything works fine. But when I quit this scene and then try to reload a second time, the SpriteAtlasManager.atlasRequested doesn't call and so all sprites are gone. I have tried to release the operation after it is finished, to save the atlases in a list and then unload them when I switch into a new scene, but nothing seems to work.

    If i don´t unload the SpriteAtlas, then the sprites are visible, but I am afraid that this might affect negatively in some way (i have multiple bundles and scenes with multiple atlases each).

    In a previous version of the addressables system, everything worked fine. I just updated to 1.10.0.

    Thank you very much for the help!
     
    SangHyukPark likes this.
  2. SangHyukPark

    SangHyukPark

    Joined:
    Dec 14, 2016
    Posts:
    1
    i used unity 2019.2.1 a few day ago but not problem
    so, i was upgrade my unity for 2019.4.1f1
    but i have same problem
    if you solve this problem, please share to me
     
  3. Mitjans_AmuseNetwork

    Mitjans_AmuseNetwork

    Joined:
    Aug 3, 2017
    Posts:
    24
    I forgot to say this, but I also upgraded unity to Unity 2019.4.1. The previous version (where everything worked) is Unity 2019.2.15f1.

    To load the scene, which is included in a remote bundle, I use
    Addressables.DownloadDependenciesAsync(address)


    and if it succeeds, I then load the scene by using
    Addressables.LoadSceneAsync(key, loadMode);


    I have observed that if I still have some resources loaded, even if I release the spriteAtlas, the sprites are still there (even if switching from one scene to another INSIDE the same bundle). When I unload all resources from the bundle and then I redo the same operation (download dependencies + load scene async) then all sprites are gone :(
     
  4. TreyK-47

    TreyK-47

    Unity Technologies

    Joined:
    Oct 22, 2019
    Posts:
    1,816
  5. Devwind

    Devwind

    Joined:
    Nov 17, 2012
    Posts:
    2
    I had the same problem with Unity 2019.4.3, everything worked fine before Unity.2019.4.1 (in my case Unity 2019.3.5f1)
    Code (CSharp):
    1. SpriteAtlasManager.atlasRequested
    is not being called after I reload the game (by unloading all asset bundles and reloading the scene), all sprites within the sprite atlas are gone, the rest remains intact.
     
  6. tealm

    tealm

    Joined:
    Feb 4, 2014
    Posts:
    108
    SpriteAtlasManager.atlasRequested is really unreliable, I noticed that sometimes the events would not be fired when used together with Addressables SpriteAtlases. I am not sure it is directly related to Addressables though, so I went ahead and made a simple test and managed to reproduce similar behavior to the bug:

    Create a Sprite atlas, add a sprite to it, and uncheck Include in Build.
    Create a UI Image and select the atlased sprite you created. Attach this script:

    Code (CSharp):
    1. using System;
    2. using UnityEngine;
    3. using UnityEngine.U2D;
    4. using UnityEngine.UI;
    5.  
    6. [RequireComponent(typeof(Image))]
    7. public class AddressableImage : MonoBehaviour
    8. {
    9.     [SerializeField] private Image image;
    10.  
    11.     private void OnEnable()
    12.     {
    13.         SpriteAtlasManager.atlasRequested += SpriteAtlasManagerOnAtlasRequested;
    14.     }
    15.  
    16.     private void OnDisable()
    17.     {
    18.         SpriteAtlasManager.atlasRequested -= SpriteAtlasManagerOnAtlasRequested;
    19.     }
    20.  
    21.     private void SpriteAtlasManagerOnAtlasRequested(string tag, Action<SpriteAtlas> arg2)
    22.     {
    23.         Debug.LogWarning(tag);
    24.     }
    25.  
    26.     protected void OnValidate()
    27.     {
    28.         Debug.Log(image.sprite); // will stop .atlasRequested event from being fired
    29.     }
    30. }
    31.  
    Notice how the event will not be fired because OnValidate runs Debug.Log(image.sprite) before event.
    I think something similar happens when I use SpriteAtlases with Addressables, where multiple users have seen events not fired. I reported this to Unity (Case 1277325).

    Since SpriteAtlasManager uses a static event I am also guessing a reference could be lingering in memory if one does not properly clean up the event.
    public static event Action<string, Action<SpriteAtlas>> atlasRequested = null;


    For me the late binding seems way to unreliable, especially when used in combination with Addressable SpriteAtlases - I am staying away from this for now.
     
  7. tealm

    tealm

    Joined:
    Feb 4, 2014
    Posts:
    108
    If I do a async load of direct reference to a single sprite in a variant atlas, I get atlasRequested invoked twice. The following script outputs:

    TestAtlas
    cursorHand_grey
    cursorHand_grey(Clone)

    TestAtlas
    cursorHand_grey(Clone)
    cursorHand_grey(Clone)

    So we get a clone from our sprite the first time, and this then apparently invokes another atlasRequested call? Is this intentional @TreyK-47 ?

    PS. The same thing happens referencing sprite in a master atlas (without variant atlas).

    Code (CSharp):
    1. using System;
    2. using UnityEngine;
    3. using UnityEngine.AddressableAssets;
    4. using UnityEngine.ResourceManagement.AsyncOperations;
    5. using UnityEngine.U2D;
    6. using UnityEngine.UI;
    7.  
    8. [RequireComponent(typeof(Image))]
    9. public class AddressableImage : MonoBehaviour
    10. {
    11.     [SerializeField] private Image image;
    12.  
    13.     private void OnEnable()
    14.     {
    15.         SpriteAtlasManager.atlasRequested += SpriteAtlasManagerOnAtlasRequested;
    16.     }
    17.  
    18.     private void OnDisable()
    19.     {
    20.         SpriteAtlasManager.atlasRequested -= SpriteAtlasManagerOnAtlasRequested;
    21.     }
    22.  
    23.     private void SpriteAtlasManagerOnAtlasRequested(string tag, Action<SpriteAtlas> arg2)
    24.     {
    25.         Debug.LogWarning(tag);
    26.  
    27.         var op = Addressables.LoadAssetAsync<Sprite>($"Atlas/TestAtlasVariant.spriteatlas[cursorHand_grey]");
    28.         Debug.Log(image.sprite.name);
    29.         op.Completed += OpOnCompleted;
    30.     }
    31.  
    32.     private void OpOnCompleted(AsyncOperationHandle<Sprite> op)
    33.     {
    34.         var sprite = op.Result;
    35.         Debug.Log(sprite.name);
    36.         image.sprite = sprite;
    37.     }
    38. }
     
  8. tealm

    tealm

    Joined:
    Feb 4, 2014
    Posts:
    108
    Bug confirmed by Unitys QA team.

    Will also report the second case here as a seperate bug just to be sure they pick it up. SpriteAtlasManager.atlasRequested will be invoked again after you load any bundle (Addressable.LoadAsync) which contains a sprite/atlas like in the example above. This again leads to the next atlasRequested silently failing for future atlasRequested events...

    Code (CSharp):
    1. private void SpriteAtlasManagerOnAtlasRequested(string tag, Action<SpriteAtlas> callback)
    2.     {
    3.         Debug.LogWarning(tag);
    4.         var address = $"Atlas/AtlasFoobar.spriteatlas";
    5.         Debug.Log(address);
    6.  
    7.         // causes atlasRequested event to be invoked again on same atlas, and next atlasRequested event to silently fail/disappear.
    8.         // (ie: loading a new scene with a sprite assigned to addressable atlas)
    9.         var op = Addressables.LoadAssetAsync<SpriteAtlas>(address);
    10.     }
     
  9. davidla_unity

    davidla_unity

    Unity Technologies

    Joined:
    Nov 17, 2016
    Posts:
    762
    Given that it seems like upgrading the Editor version is what's causing the issue I'm inclined to think this is something the Sprite team will need to look at. I appreciate the bugs getting filed though. If it does end up being something on our end we'll get it looked at and taken care of.
     
  10. tealm

    tealm

    Joined:
    Feb 4, 2014
    Posts:
    108
    The first bug got a by design response from devs.

    Our developers have reviewed this issue and it has been concluded that this behaviour is by design:
    "Since OnValidate awakes the Sprite even before entering Playmode, the atlasRequested does not get registered by design"

    Anyhow the repeated atlasRequested that is invoked when loading a SpriteAtlas with Addressable.LoadAsync is for sure a bug, and hopefully they will look into it. I have not gotten a confirmation from QA for this bug though.. not sure if you can put some pressure on it @DavidUnity3d ? We have removed all our addressable SpriteAtlases binding through atlasRequested because it is so unreliable to use.

    We are instead loading each sprite from the atlas separately, as that seems to be the only safe way to have it work for now. Sucks that we have to do 30 LoadAssetAsync for our 30 sprites in a atlas instead of just one LoadAssetAsync call..
     
    Last edited: Sep 27, 2020
Thread Status:
Not open for further replies.