Search Unity

[Solved, sorta] How to use UnityWebRequest to read local .jpg?

Discussion in 'Scripting' started by Hunubul, Feb 12, 2019.

  1. Hunubul

    Hunubul

    Joined:
    Dec 17, 2018
    Posts:
    65
    Hey! Sorry I've been pretty irritated lately because of work. And sorry for the huge wall of text as well.

    I've been putting aside this project for a month, and now it doesn't work after updating Unity.
    I use panoramic shader to put a 360 stereo pic to the skybox. I try using UnityWebRequest:

    Code (CSharp):
    1. path="C:/test/file.jpg"
    2. StartCoroutine(GetText());
    3. skybox.SetTexture("_Tex", t);
    4.  
    5. IEnumerator GetText()
    6.         {
    7.             using (UnityWebRequest uwr = UnityWebRequestTexture.GetTexture(path))
    8.             {
    9.                 yield return uwr.SendWebRequest();
    10.  
    11.                 if (uwr.isNetworkError || uwr.isHttpError)
    12.                 {
    13.                     Debug.Log(uwr.error);
    14.                 }
    15.                 else
    16.                 {
    17.                     // Get downloaded asset bundle
    18.                     t = DownloadHandlerTexture.GetContent(uwr);
    19.                 }
    20.             }
    21.         }
    BTW I started using WWW because I need to use my script on videos as well, and storing it as url was the best option, and I also want to use the script on android, thus other methods didn't seem efficient. If there is a better way to read .jpgs, I would look after it and see how it works and if it would be good for me.


    EDITED because I made progress, tho no progress with UnityWebRequest.

    EDIT2: I don't like UWR.
     
    Last edited: Feb 14, 2019
  2. Hunubul

    Hunubul

    Joined:
    Dec 17, 2018
    Posts:
    65
    UPDATE: I got it working with WWW and the built in panoramic shader.

    So my question would be how to make it work with UnityWebRequest, because it did nothing for me... When I use it like WWW it says it's unfinished, and the way it was in the documentation does not work.

    Working code:

    Code (CSharp):
    1. byte[] fileData;
    2. WWW reader;
    3. reader = new WWW(path);
    4. fileData = reader.bytes;
    5. t.LoadImage(fileData);
    6. skybox.SetTexture("_MainTex", t);
     
  3. Hosnkobf

    Hosnkobf

    Joined:
    Aug 23, 2016
    Posts:
    1,096
    I think the problem is this:
    Code (CSharp):
    1. path="C:/test/file.jpg"
    if you are downloading something from the web you have a prefix
    http://
    or
    https://
    . If you "download" something from your file system, you also need a prefix:
    file://

    So, probably it works if you change the line to:
    Code (CSharp):
    1. path="file://C:/test/file.jpg"
    PS: I would not go for WWW and use the UnityWebRequest. There is a reason why unity changed it. And I think the reason is, that the WWW class can cause a memory leak, since it may never be disposed.

    PPS: I am not 100% sure but I think you cannot use a Texture2D for a skybox. You need a Cubemap instead.
     
  4. Hunubul

    Hunubul

    Joined:
    Dec 17, 2018
    Posts:
    65
    Sadly still doesn't work with file:// added to path.

    Texture2D is what panoramic shader skybox material uses, and it works when I use WWW, so that shouldn't be the problem.
    EDIT: Yeah, the shader I use is spherical and uses Texture2D. I didn't find anything else that could work the way I want it to. So the only problem is that I can't grasp how to use UnityWebRequest. I only need it because of android (if I get it to work finally), and because or the video player. It's much better to just give it an url, and I found that I could only do it via WWW, so I should be able to do it with UnityWebRequest now.

    Also is there a line that can make UnityWebRequest wait, or do I need to use the method above (and in the documentation) every time?

    BTW thanks for the response. While it would be logical I didn't think of putting a prefix to the path.
     
    Last edited: Feb 12, 2019
  5. Hunubul

    Hunubul

    Joined:
    Dec 17, 2018
    Posts:
    65
    I tried file:// I tried file:///, I tried creating a Uri and it still doesn't work. Can anyone share a working code using UnityWebRequest to load a local .jpg? I have no idea what I'm missing.
     
  6. Hosnkobf

    Hosnkobf

    Joined:
    Aug 23, 2016
    Posts:
    1,096
    This is code from a project where I use it:
    Code (CSharp):
    1.             using (UnityWebRequest loader = UnityWebRequestTexture.GetTexture("file://" + FilePath))
    2.             {
    3.                 yield return loader.SendWebRequest();
    4.  
    5.                 if (string.IsNullOrEmpty(loader.error))
    6.                 {
    7.                     _texture = DownloadHandlerTexture.GetContent(loader);
    8.                 }
    9.                 else
    10.                 {
    11.                     this.LogErrorFormat("Error loading Texture '{0}': {1}", loader.uri, loader.error);
    12.                 }
    13.             }
    looks pretty much the same as yours.
     
    BitGamey likes this.
  7. Hunubul

    Hunubul

    Joined:
    Dec 17, 2018
    Posts:
    65
    This is so stupid. I had to put the texture change in the if. And it's slow. Is there a way to speed up UnityWebRequest? With WWW it was around a second to load only one .jpg. With UWR it takes 3. That isn't acceptable IMO.
    Code (CSharp):
    1. IEnumerator GetText()
    2.         {
    3.             using (UnityWebRequest uwr = UnityWebRequestTexture.GetTexture(path))
    4.             {
    5.                 yield return uwr.SendWebRequest();
    6.  
    7.                 if (uwr.isNetworkError || uwr.isHttpError)
    8.                 {
    9.                     Debug.Log(uwr.error);
    10.                 }
    11.                 else
    12.                 {
    13.                     // Get downloaded asset bundle
    14.                     t = DownloadHandlerTexture.GetContent(uwr);
    15.                     skybox.SetTexture("_MainTex", t);
    16.                 }
    17.             }
    18.         }
    I don't like this code at all. I'm really angry how it works now. I get that WWW wasn't great and stuff, but it was acceptable to use. This is outrageous how it looks, and how inefficient it is to load local files with it.
     
  8. Hunubul

    Hunubul

    Joined:
    Dec 17, 2018
    Posts:
    65
    Thanks, yeah it's pretty much the same. Even in your code, just to test, I had to put the texture change within the if. And it still takes 2-3 seconds to load just one image. Pretty inefficient, expecially compared to WWW. Can you suggest a better way to load .jpgs?
    EDIT: I need a way to load .jpgs that work on Oculus Go as well. I couldn't load .jps there yet, but I'd like to.

    EDIT: Another problem is that the script doesn't wait for the dowload to finish (even tho there doesn't have to be any download), thus if I wanna load more pics it takes forever and I can't see the pics, only if I change it after it has finished, manually as of yet.
     
    Last edited: Feb 12, 2019
  9. Hosnkobf

    Hosnkobf

    Joined:
    Aug 23, 2016
    Posts:
    1,096
    If it takes 2-3 seconds to load, you either have a very slow machine or a huge texture.
    In my application I do it like this:
    I download the texture from the internet and save it to disk, then dispose the texture. This takes usually less than a second (on mobile).
    Later, when I need the texture I load it from disk. Loading it is barely noticeable.

    Maybe you have some other problem in your code. Can you show more of the surrounding logic?
     
    jaimelugo likes this.
  10. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    3,736
    Which version are you one?
    Since 2017.1 WWW is a thin wrapper on top of UnityWebRequest, with difference being that WWW does texture load on main thread (right at the time when you access texture property), while UWR does most texture creation on background thread. That can make a difference if measurements are not placed well.
     
  11. Hunubul

    Hunubul

    Joined:
    Dec 17, 2018
    Posts:
    65
    I really don't get how this works, and don't get why it works this way.
    I made a test script, so this is the only code it has. The .jpg is ~4000*4000, 47,3 MB because it's bad quality only for testing. But I'll share the whole code just to be safe:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.Networking;
    5. using System;
    6.  
    7. public class teszt : MonoBehaviour
    8. {
    9.     private string path;
    10.     public Material skybox;
    11.     // Start is called before the first frame update
    12.     void Start()
    13.     {
    14.         path = "file:///C:/TEST/test.jpg";
    15.         Texture2D t;
    16.         t = new Texture2D(2, 2);
    17.      
    18.         StartCoroutine(GetText());
    19.         skybox.SetTexture("_MainTex", t);//This one does nothing
    20.  
    21.         // Update is called once per frame
    22.         void Update()
    23.         {
    24.  
    25.         }
    26.         IEnumerator GetText()
    27.         {
    28.             using (UnityWebRequest uwr = UnityWebRequestTexture.GetTexture(path))
    29.             {
    30.                 yield return uwr.SendWebRequest();
    31.                 if (string.IsNullOrEmpty(uwr.error))
    32.                 {
    33.                     // Get downloaded asset bundle
    34.                     t = DownloadHandlerTexture.GetContent(uwr);
    35.                     skybox.SetTexture("_MainTex", t);
    36.                     //if I change texture here it works
    37.                 }
    38.                 else
    39.                 {
    40.                     Debug.Log(uwr.error);
    41.                 }
    42.              
    43.             }
    44.         }
    45.     }
    46. }
    I use latest Unity, 2018.3.5, thus I get a S***load of warnings for using WWW.

    So does anyone know why my code is slow?

    EDIT: PC isn't a problem, 16GB ram, 1070 TI, processor also pretty nice. I can share the whole specs, but the point is, the computer isn't slow.
     
    Last edited: Feb 13, 2019
  12. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    3,736
  13. Hosnkobf

    Hosnkobf

    Joined:
    Aug 23, 2016
    Posts:
    1,096
    About why it doesn't work outside of the method:
    You are assigning it right after starting the coroutine. At this point the coroutine is idling at the
    yield return
    statement. In other words: The texture has not yet been loaded because the loading of the texture is not synchronous. So you need to set the texture either after loading and assigning it or you make a callback parameter which is invoked at that point and put the logic in that callback method.

    However: 47 MB is a lot it is about 2/3rd of the size a BMP would have with that resolution. The Images I was referring to where less than 2 MB.
    Maybe you play a bit with compression to get smaller image sizes. Is the quality acceptable if you compress it via TinyPNG?
    Edit: Sorry, just realized that TinyPNG has a maximum image file size which is much too low for you (even if you would pay).
     
  14. Hunubul

    Hunubul

    Joined:
    Dec 17, 2018
    Posts:
    65
    I'll be using lot bigger pictures later on. Think about a few hundred MB.

    With WWW the same thing was instant, so I guess I shouldn't use URW at all, doesn't seem optimal for the task.


    Does this work on android devices? This was the first method I used, but later decided WWW would be better, but URW and WWW seems to be out of the question, so I'll stick with this for the time being, thanks.
     
  15. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    3,736
    This cannot be true. WWW is a wrapper on top UWR, so the same performance is achievable using UWR directly.
    The difference is that WWW will use DownloadHandlerBuffer and then ImageConversion to turn bytes into texture, but the performance difference cannot be massive, it's more likely your measurements are wrong.
     
  16. Hunubul

    Hunubul

    Joined:
    Dec 17, 2018
    Posts:
    65
    There is a huge time difference, dunno why. Anyway I'm starting to hate UWR and I won't use it. Hope I won't need to.
     
  17. MaskedMouse

    MaskedMouse

    Joined:
    Jul 8, 2014
    Posts:
    1,092
    WWW is deprecated, so yeah you will have to use UWR eventually.
    Besides what the Unity rep tells you here is, is that WWW actually calls UWR for you... so either way you're calling UWR directly or WWW does it for you... there shouldn't be a performance difference.
     
    Last edited: Feb 13, 2019
  18. Hosnkobf

    Hosnkobf

    Joined:
    Aug 23, 2016
    Posts:
    1,096
    If I understand it correctly, the way WWW is implemented now is like this:
    Code (CSharp):
    1. using (UnityWebRequest uwr = UnityWebRequest.Get(path))
    2. {
    3.     yield return uwr.SendWebRequest();
    4.     if (string.IsNullOrEmpty(uwr.error))
    5.     {
    6.         t.LoadImage(uwr.downloadHandler.data);
    7.     }
    8.     else
    9.     {
    10.         Debug.Log(uwr.error);
    11.     }
    12. }
    maybe you can try this and check if it is faster.
    Would be nice if you could measure the time by using a System.Diagnostics.Stopwatch which you start when entering the coroutine method and stop (and log) at the end of the method. Then do that for both approaches and share the results. I would be very interested :)
     
  19. Hunubul

    Hunubul

    Joined:
    Dec 17, 2018
    Posts:
    65
    I did that, here's the conclusion:
    UWR method, like in documentation: ~00:00:02.6000000, or ~00:00:01.5000000, or sometimes ~ 00:00:03.0000000 or even 00:00:04.5000000 happened.
    WWW method, like I did at the beginning: ~00:00:01.5000000 consistently.
    Your method also acts like the UWR method from the documentation, sometimes WWW speed, sometimes slow, but always below 00:00:03.0000000.
    Readbytes is just a tiny bit faster than WWW was.

    It's not always slower, but inconsistency is even worse than low speed. Seems readbytes is best, but WWW was more than acceptable. UWR seems to be unacceptable from this small experiment. I don't wanna know what would've happened with 300MB files.
     
  20. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    3,736
  21. Hunubul

    Hunubul

    Joined:
    Dec 17, 2018
    Posts:
    65
    It can't be faster, yet it is. It may be because the patch screwed something up, and UWR isn't working as intended. Erratic behaviour is never intended, so my guess is that this shouldn't be the case. Yet it is. I ran the program, I got the times, and the program doesn't lie. Doesn't matter how it should be on paper, because I don't use the code on paper, I use it in the program. You don't have to explain. I don't just make this up. It is what it is, I accept it, you should too.

    Or you can even conduct your own tests, and maybe even figure out why it happens. I wrote a fresh code, this is the only thing running, so you should get the same results.
     
  22. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    3,736
    How do you measure it? Can you show the code that includes the measuring too?
     
  23. Hunubul

    Hunubul

    Joined:
    Dec 17, 2018
    Posts:
    65
    Code (CSharp):
    1. System.Diagnostics.Stopwatch tiem = new System.Diagnostics.Stopwatch();
    2. tiem.Start();
    3. tiem.Stop();
    4. Debug.Log(tiem.Elapsed);
    I did just how it was asked by Hosnkobf. Start when entering coroutine, stop when leaving coroutine. For WWW just before creating the WWW, and right after loading the image. Same with file.ReadAllBytes. The problem isn't with speed, there were times when it was the same. Inconsistency is what bugs me, there shouldn't be any. Thus I'll forget UWR even exists, there are a lot more things I don't like about them, so I'll just listen to my gut and never use it. Doesn't matter how good it is, doesn't matter what I'll be doing.

    I got my results, I know I'll only be using ReadAllBytes for this. For videos I'll use Uri. I hope that's compatible with video player url source, but that's a test for later. And I hope it'll work on Oculus Go.

    EDIT: Also I didn't just run it once. I run it like 20-30 times to get different results. WWW and ReadAllBytes were consistent, always same speed. I made sure I can form an opinion against UWR.
     
  24. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    3,736
    I mean full code, that also includes the WWW/UWR.
     
  25. Hunubul

    Hunubul

    Joined:
    Dec 17, 2018
    Posts:
    65
    Code (CSharp):
    1. using System.Collections;
    2. using UnityEngine;
    3. using UnityEngine.Networking;
    4. using System.IO;
    5.  
    6. public class test : MonoBehaviour
    7. {
    8.     private string path;
    9.     void Start()
    10.     {
    11.         path = "file:///C:/test/test.jpg";
    12.         Texture2D t;
    13.         t = new Texture2D(2, 2);
    14.  
    15.  
    16.         System.Diagnostics.Stopwatch tiem = new System.Diagnostics.Stopwatch();
    17.         tiem.Start();
    18.         StartCoroutine(GetText());
    19.  
    20.         System.Diagnostics.Stopwatch tiemb = new System.Diagnostics.Stopwatch();
    21.         tiemb.Start();
    22.         byte[] fileData;
    23.         WWW reader;
    24.         reader = new WWW(path);
    25.         fileData = reader.bytes;
    26.         t.LoadImage(fileData);
    27.         tiemb.Stop();
    28.         Debug.Log("WWW"+tiemb.Elapsed);
    29.  
    30.         System.Diagnostics.Stopwatch tiemc = new System.Diagnostics.Stopwatch();
    31.         tiemc.Start();
    32.         StartCoroutine(GT2());
    33.  
    34.  
    35.         System.Diagnostics.Stopwatch tiemd = new System.Diagnostics.Stopwatch();
    36.         tiemd.Start();
    37.         path = "C:/test/test.jpg";
    38.         fileData = File.ReadAllBytes(path);
    39.         t.LoadImage(fileData);
    40.         tiemd.Stop();
    41.         Debug.Log("readbytes"+tiemd.Elapsed);
    42.  
    43.  
    44.         // Update is called once per frame
    45.         void Update()
    46.         {
    47.  
    48.         }
    49.         IEnumerator GetText()
    50.         {
    51.             using (UnityWebRequest uwr = UnityWebRequestTexture.GetTexture(path))
    52.             {
    53.                 yield return uwr.SendWebRequest();
    54.                 if (string.IsNullOrEmpty(uwr.error))
    55.                 {
    56.                     // Get downloaded asset bundle
    57.                     t = DownloadHandlerTexture.GetContent(uwr);
    58.                     tiem.Stop();
    59.                     Debug.Log("UWR"+tiem.Elapsed);
    60.                 }
    61.                 else
    62.                 {
    63.                     Debug.Log(uwr.error);
    64.                 }
    65.                
    66.             }
    67.         }
    68.         IEnumerator GT2()
    69.         {
    70.             using (UnityWebRequest uwr = UnityWebRequest.Get(path))
    71.             {
    72.                 yield return uwr.SendWebRequest();
    73.                 if (string.IsNullOrEmpty(uwr.error))
    74.                 {
    75.                     t.LoadImage(uwr.downloadHandler.data);
    76.                     tiemc.Stop();
    77.                     Debug.Log("forumguy" + tiemc.Elapsed);
    78.                 }
    79.                 else
    80.                 {
    81.                     Debug.Log(uwr.error);
    82.                 }
    83.             }
    84.  
    85.         }
    86.     }
    87. }
    I know you think I'm actually retarded, but a simple speed check is something I can do. I created 4 different timers so they can work simultaneously.

    Do the test yourself if you want, but I don't really want to use UWR anymore, whatever the outcome of any test.

    I also have Unity 2018.3.5, which may be important information. I had to rewrite my code because of the update, so yeah. I'm happy.
     
  26. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    3,736
    If you measure like that (all at once) and you use WWW like that, your measurements are incorrect!

    By just creating WWW and then taking bytes (or texture) out of it you force it to busy-wait right there until request is finished. That means that your first coroutine, which is started before WWW, does not get a chance to finish until after WWW (actually the whole Start()) is done. Coroutines are just another Update() methods, if Start() is busy, Update does not execute.

    Since you are reading local files, you should test each different reading type individually, because otherwise they affect each other.
    I gave a link to WWW source code before. If you check the WaitUntilDoneIfPossible() in it, you'll see it spinning a busy loop on an underlying UWR instance.

    It is recommended to use coroutine for WWW too, then file will be read on a background thread instead of making your game hang. And that hang would be way worse on android. Stopwatches are also best to place inside coroutine methods themselves.

    The exactly same performance is definitely achievable using UWR, because that's what WWW uses internally!
     
    nilsdr likes this.
  27. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    3,736
    Add to that - there is a very small chance the performance is different because of how coroutine is handled by WWW and UWR, but it's unlikely and it would mean a serious bug if it makes a big difference. But that has to be proven first.

    You have to be careful about measuring performance, especially when using coroutines, since they are tied to update loops, so the time you get will always be in frames and one frame difference kind of means nothing (the task can be 99.99% done at he time of update, but it will wait for the next frame).
     
    nilsdr likes this.
  28. Hunubul

    Hunubul

    Joined:
    Dec 17, 2018
    Posts:
    65
    I want it to wait, and not to run in the background, because I want to see the image. I didn't find this wait function you shared now, so thanks. I'll may still try to use it.

    Thanks, I'll still stick to ReadAllBytes, because I don't want a coroutine, I don't want background work to be done. I'm a simple man with simple needs: to load an image, then show the image. I could easily do that with WWW, but with UWR I couldn't find how to do that, and even now I found it too... Well the code is ugly IMO, and bigger. Which I hate.
     
  29. Hosnkobf

    Hosnkobf

    Joined:
    Aug 23, 2016
    Posts:
    1,096
    Wow, you are using local methods. I was not aware that unity already supports that!
    However, I refactored your code to get more reliable test results:
    Code (CSharp):
    1.  
    2. using System.Collections;
    3. using UnityEngine;
    4. using UnityEngine.Networking;
    5. using System.IO;
    6.  
    7. public class TestTime : MonoBehaviour
    8. {
    9.     private const string path = "C:/test/test.jpg";
    10.     private const string pathWithPrefix = "file://C:/test/test.jpg";
    11.  
    12.     IEnumerator Start()
    13.     {
    14.         const int iterations = 100;
    15.         yield return StartCoroutine(TestTimeRoutine("UWR Texture",  iterations, TestTimeForUwrTexture));
    16.         yield return StartCoroutine(TestTimeRoutine("UWR Bytes",    iterations, TestTimeForUwrBytes));
    17.         yield return StartCoroutine(TestTimeRoutine("WWW Texture",  iterations, TestTimeWWWTexture));
    18.         yield return StartCoroutine(TestTimeRoutine("WWW Bytes",    iterations, TestTimeWWWBytes));
    19.         yield return StartCoroutine(TestTimeRoutine("Direct Load",  iterations, TestTimeDirectLoad));
    20.     }
    21.  
    22.     IEnumerator TestTimeRoutine(string testTitle, int iterations, System.Func<IEnumerator> innerRoutine)
    23.     {
    24.         System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();
    25.         watch.Start();
    26.         for (int i = 0; i < iterations; i++)
    27.         {
    28.             yield return StartCoroutine(innerRoutine());
    29.         }
    30.         watch.Stop();
    31.  
    32.         Debug.LogFormat("{0} - iterations: {1} - total time: {2} ms - average time: {3} ms",
    33.             testTitle, iterations, watch.ElapsedMilliseconds, watch.ElapsedMilliseconds / iterations);
    34.     }
    35.  
    36.     IEnumerator TestTimeForUwrTexture()
    37.     {
    38.         Texture tex = null;
    39.         using (UnityWebRequest uwr = UnityWebRequestTexture.GetTexture(pathWithPrefix))
    40.         {
    41.             yield return uwr.SendWebRequest();
    42.             if (string.IsNullOrEmpty(uwr.error))
    43.             {
    44.                 // Get downloaded asset bundle
    45.                 tex = DownloadHandlerTexture.GetContent(uwr);
    46.             }
    47.             else
    48.             {
    49.                 Debug.Log(uwr.error);
    50.             }
    51.  
    52.         }
    53.     }
    54.  
    55.  
    56.     IEnumerator TestTimeForUwrBytes()
    57.     {
    58.         Texture2D tex = new Texture2D(2, 2);
    59.         using (UnityWebRequest uwr = UnityWebRequest.Get(pathWithPrefix))
    60.         {
    61.             yield return uwr.SendWebRequest();
    62.             if (string.IsNullOrEmpty(uwr.error))
    63.             {
    64.                 tex.LoadImage(uwr.downloadHandler.data);
    65.             }
    66.             else
    67.             {
    68.                 Debug.Log(uwr.error);
    69.             }
    70.         }
    71.     }
    72.  
    73.     IEnumerator TestTimeWWWTexture()
    74.     {
    75.         Texture2D tex = null;
    76.         WWW reader = new WWW(pathWithPrefix );
    77.         yield return reader;
    78.      
    79.         tex = reader.texture;
    80.     }
    81.  
    82.     IEnumerator TestTimeWWWBytes()
    83.     {
    84.         Texture2D tex = new Texture2D(2, 2);
    85.         WWW reader = new WWW(pathWithPrefix );
    86.         yield return reader;
    87.  
    88.         byte[] data = reader.bytes;
    89.         tex.LoadImage(data);
    90.     }
    91.  
    92.     IEnumerator TestTimeDirectLoad()
    93.     {
    94.         Texture2D tex = new Texture2D(2, 2);
    95.         byte[] data = File.ReadAllBytes(path);
    96.         tex.LoadImage(data);
    97.         yield break;
    98.     }
    99.  
    100. }
    Note: not tested by myself.

    Edit: fixed WWW method which was had a copy paste problem
     
    Last edited: Feb 15, 2019
    victorbadea likes this.
  30. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    3,736
    For even better results you should perform reads one at the time, rather than all at once, since you can bottleneck on disk I/O.
    If you want to perform similar test on phones, i.e. Android, things get even trickier, because the phone can overheat and get throttled and whatever you place last can appear slow, even though it not necessarily is.
     
    nilsdr likes this.
  31. Hosnkobf

    Hosnkobf

    Joined:
    Aug 23, 2016
    Posts:
    1,096
    The code I posted does it one at a time.
     
  32. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    3,736
    You're right, sorry.
     
  33. unity_A-AtY_Ce2ONPBg

    unity_A-AtY_Ce2ONPBg

    Joined:
    May 14, 2020
    Posts:
    1
    How do we access an image from a shared folder in this scenario? Lets us say two machines are connected in a private network. Unity application is running in one machine and there are images that need to be accessed from the second machine. Will UnityWebRequest still work in this scenario?
     
  34. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    3,736
    This does work in Editor and Standalones, but not in all platforms. On Windows you should be able to use file:// protocol with host provided, on Mac smb:// protocol does work (probably work on Windows too). If it's a shared drive, accessible on Windows via \\machine\path and on OSX via ///machine/path, then you should be able to use file:// protocol as well, just make sure you have correct number of slashes after file: (should be five).
     
    unity_A-AtY_Ce2ONPBg likes this.
  35. ubergeekseven

    ubergeekseven

    Joined:
    Oct 27, 2014
    Posts:
    5
    OH MY GOD FINALLY!!!!!!!!!!!!!!!!!!!! This worked for my needs. I never saw this reference in docs at all. Thank you!!!!
     
    Jd_Parmar likes this.
  36. jaimelugo

    jaimelugo

    Joined:
    Nov 8, 2019
    Posts:
    27
    I know I am coming late to the party... but after experimenting with LoadImage() and Webrequest Get.... the code above is by far the best one when it comes to speed and it works with android...

    Just one remark for memory management, id you add the uwr.Dispose(); after you assigned the texture, it will help you loads with the memory management in android.