- Home /
Unity hangs when trying to load an image from url using the WWW class
Unity version: 5.4.1 Platform: Windows
Hello, I am trying to load an image from a url into a texture using the WWW.LoadImageIntoTexture() method. Whenever I do this though, the game will freeze for about half a second to a full second before resuming normally. Here is the code:
IEnumerator GetTexture () {
Texture2D tex = new Texture2D (4, 4, TextureFormat.DXT1, false);
WWW www = new WWW (url);
yield return www;
www.LoadImageIntoTexture (tex);
Renderer imageMAT = GetComponent<Renderer>();
imageMAT.material.SetTexture("_Main",tex);
int height = imageMAT.material.GetTexture("_Main").height;
int width = imageMAT.material.GetTexture("_Main").width;
float verticalScale = (float)height / (float)width;
gameObject.transform.localScale = new Vector3 (1f, verticalScale, 1f);
}
Where 'url' is a string that directs to an image online.
It's to my understanding that WWW is supposed to be asynchronous (correct me if I'm wrong in assuming this) but what's really puzzling me are the results I'm getting from the Unity Profiler. When I use the profiler, I see there is a clear spike where the frame takes 571 ms to finish but according to the profiler, the thing that is taking so long is called "iTween.SetupCoroutine()[Coroutine: InvokeMoveNext]".
I am using iTween in this project, but not anywhere in this script. I looked through the iTween script and I couldn't find a method called "SetupCoroutine" or anything called "InvokeMoveNext". It is also worth mentioning that when I select that line in the profiler to view details in the window on the right, the 'Object' column tells me that the object calling 'iTween.SetupCoroutine' is 'N/A'.
According to this, the hang was half a second. I added in some Debug statements to see what the difference in Time.time was between completion of the www call and the LoadImageIntoTexture line and the result was that the www call took a little over 1 second to complete. So if the hang was only half of that and WWW is supposed to be asynchronous, then I don't think that the www call is the reason for the hang, but then I have no idea what could be causing it. The 'www.LoadImageIntoTexture(tex)' line happens instantaneously, so I don't think it's that either.
Any ideas on what could be causing this or what the iTween.SetupCoroutine is referring to, or at least where I should try looking next? Any guidance is greatly appreciated, thanks!
Answer by Bunny83 · Oct 06, 2016 at 03:30 AM
WWW is asynchronous. At the moment it's not clear where you start that coroutine you've shown. You should create a "deep profile" (enable the toggle at the top) and examine further down what might cause this spike. Note that your coroutine does some heavy things after the request has finished.
LoadImageIntoTexture might has to decompress and recompress the texture as you want it as DXT1
using "imageMAT.material" will duplicate the material that the renderer currently uses. It might have an impact if the object was batched before.
(Why do you use "GetTexture" when you can simply use tex.height and tex.width ?)
Changing the scale of an object can have an impact depending on the object, For example the physics system has to rebuild the collider. It the object as marked as static this can have a huge impact as this shouldn't be done at all ^^.
In the end you have to first track down the actual offending source by looking at the deep profile.
Thanks! I ran a deep profile and it turned out the cause was WWW.LoadImageIntoTexture. DXT1 was recommended by a friend of $$anonymous$$e and I just blindly followed it. That was the cause. I changed the format to RGB24 and the hang dropped down to 103 ms. Not perfect, but I'm willing to accept it. At that point, I think it's because the URL in the sample JSON file my employer provided is a really high resolution (3000x2000). I'll have to talk to them about that.
Based on the things you said were heavy operations, I'm not sure how much more I can optimize it. Duplicating the material is necessary because this texture loading is done several times for different objects as I'm reading the URLs from a JSON file (Not all in one frame, $$anonymous$$d. They're split up by a delay). The object this is being loaded onto is a quad that moves on it's own (so it's not static) but it doesn't have a collider.
As for the "GetTexture", I don't remember why I did that. Earlier, I was having some problems getting the height of the texture because of some differences between a "Texture" and a "Texture2D" and I recall that had something to do with it. I made the change you suggested and it still works, so there's that.
At any rate, thanks for the tip about the deep profile! Everything is working much faster now.
Your answer

Follow this Question
Related Questions
WWW not getting site that doesn't end on .html 1 Answer
Load image from url in Webplayer 1 Answer
UriFormatException: Invalid URI: Invalid port number for VirtualBox server using IPv6 Address 1 Answer
Cannot load image from URL passed as parameter 0 Answers
Concurrent coroutines working on same datastructure hang unity! 2 Answers