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

Loading 250+ images from Local Storage without the app freezing!

Discussion in 'Scripting' started by john-essy, Mar 18, 2019.

  1. john-essy

    john-essy

    Joined:
    Apr 17, 2011
    Posts:
    464
    So i am currently developing an app for a national park in Africa and have currently hit a snag. I download the images to the users device if they do not exist locally to be used by the app. The problem is with my current approach.

    I go through all the animals data and apply all of this to the animals page then also apply the image from local storage. When i do this the app freezes and currently on my PC it takes over 8 seconds to load the pictures into the sprite. Again remembering there are over 100 animals being loaded here.

    How would you load all these images and remove the hang of the app? This is the code i use to load the images to sprites. My biggest concern here is that in the apps "Birds section" there are over 250 images.

    Code (CSharp):
    1. Stopwatch timer = new Stopwatch();
    2.          timer.Start();
    3.          using (UnityWebRequest uwr = UnityWebRequestTexture.GetTexture("File:///"+Application.persistentDataPath + "/" + FilePath + ".jpg"))
    4.          {
    5.              yield return uwr.SendWebRequest();
    6.              if (uwr.isNetworkError || uwr.isHttpError)
    7.              {
    8.                  UnityEngine.Debug.Log(uwr.error);
    9.              }
    10.              else
    11.              {
    12.                  //// Get downloaded asset bundle
    13.                  var texture = DownloadHandlerTexture.GetContent(uwr);
    14.                  var NewSprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), new Vector2(0, 0), PixelsPerUnit, 0, spriteType);
    15.                  UnityEngine.Debug.Log("NS:::::::::::::::::" + NewSprite);
    16.                  onComplete(NewSprite);
    17.                  timer.Stop();
    18.                  TimeSpan timeTaken = timer.Elapsed;
    19.                  UnityEngine.Debug.Log("Time Taken To Load Images " + timeTaken);
    20.              }
    21.          }
     
  2. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,186
    For something like this, I wouldn't try to do everything at once. I would probably assetbundle the images and maybe download that up front, but only extract and create sprites as I needed. There are ways to cache the assetbundle so it doesn't have to be downloaded again.

    Otherwise, if you need to do it with each image, then only download what you need when you need it and not everything up front. I've done this with apps that have a store front for example where as you scroll I go and fetch the image and it just has a loading indicator where the image should be while it downloads. Then it only grabs what it needs. In this particular case, I've used json to drive the text and then grab the image on it's own. You could save the image to the device if you wanted, but if the user can find the persistantDataPath, they could get the image if you did it that way.
     
  3. john-essy

    john-essy

    Joined:
    Apr 17, 2011
    Posts:
    464
    Cheers Brathnann! So as you scroll how would you know to locate that file? Is there an InView method or something in unity scroll?
     
  4. nilsdr

    nilsdr

    Joined:
    Oct 24, 2017
    Posts:
    374
    Hi John, your current approach is fine as far as i'm concerned, downloading files to persistent data for instance is a good way of doing things.

    There's two things you can do to (vastly) improve performance:

    - Creating a sprite from the texture is an expensive operation. Instead, use a rawimage component and apply the texture directly. So avoid the Sprite.Create call https://docs.unity3d.com/ScriptReference/UI.RawImage-texture.html

    - Use some method to determine whether or not a ui element is visible, and load the image only then. This post should get you going: https://forum.unity.com/threads/test-if-ui-element-is-visible-on-screen.276549/#post-2978773
     
    john-essy likes this.
  5. john-essy

    john-essy

    Joined:
    Apr 17, 2011
    Posts:
    464
    Wha!!!

    I did not know rawImage would help here! I have ended up going down the route of a smaller res image for thumbnails and a high res image for the larger images but might actually change this to try the raw image and see the different in image load times!

    Thank you so much!
     
  6. john-essy

    john-essy

    Joined:
    Apr 17, 2011
    Posts:
    464
    I just tested the raw image approach with 325 animal profiles! it went from originally 22 seconds to < 2 seconds! That mixed with the whats visible approach is going to make it near instant and exactly what i needed! nilsdr!

    Thank you very very much!
     
    tonialatalo and nilsdr like this.
  7. nilsdr

    nilsdr

    Joined:
    Oct 24, 2017
    Posts:
    374
    No problem, good luck on your app
     
    john-essy likes this.