In my VR app for Android Smartphones (I think it doesn't matter whether it is a VR app or not) I download 6 big images from Street View and built a skybox out of it. During this process the whole app incl. environment and UI freezes. After ~10sec the process is down and Street View is there.
How can I seperate the main processing from UI? So the phone is working, but should not freeze. This is a common web problem, but how can I solve this in Unity for Android?
Thank you!
code:
private byte[] GetStreetviewTexture(string url) {
WWW www = new WWW(url);
while (!www.isDone) ;
if (!string.IsNullOrEmpty(www.error))
{
Debug.LogWarning("Unable to DL texture: " + www.error);
}
else
{
bytes = www.texture.EncodeToPNG();
}
return bytes;
}
You probably want to use an IEnumerator to thread it with a Unity Coroutine. If you're already using this, which I'm assuming you actually are - could it be a performance issue that freezes the device? If so, check the Unity profiler and/or Unity Remote. Coroutines are, like comments suggest, not a Thread - but emulates a threaded behaviour.
Basic Coroutine code:
void SomeMethod() {
StartCoroutine(Threaded());
}
IEnumerator Threaded() {
// Do something
yield return new WaitForSeconds(3f);
}
Check out the WWW class and how to make an IEnumerator wait for download to complete
Update responding to OP's follow-up question:
How to tell when a Coroutine is done and get a value
Update responding to OPs follow-up follow-up question: This is a simplified example of your current logic/flow. NOTE: THIS DOES NOT WORK. Do not use this code as an example for how it's supposed to be done, I just want to illustrate the differences in how you should approach your problem.
void ButtonClicked() {
SetTexture()
}
void SetTexture() {
Texture texture = GetTexture()
Object.texture = texture;
}
Texture GetTexture() {
Texture texture;
StartCoroutine(DownloadTexture((textureCallback) => {
texture = textureCallback;
}));
return texture;
}
IEnumerator DownloadTexture(Action<Texture> callbackTexture)
{
WWW www = new WWW(URL);
yield return www;
callback(www.texture);
}
Not only does this not work, because a Coroutine is run asyncronously with the rest of the code, but it's not a good approach for this task.
Instead of doing
Button click -> set texture -> start download -> error setting texture -> download finished
you want:
Button click -> download texture -> wait for it to be done -> set texture
Like this:
void ButtonClick() {
StartCoroutine(DownloadTexture((callbackTexture) => {
SetTexture(callbackTexture); // Will run SetTexture when Coroutine DownloadTexture is completed.
}));
}
IEnumerator DownloadTexture(Action<Texture> callbackTexture)
{
WWW www = new WWW(URL);
yield return www;
callback(www.texture);
}
void SetTexture(Texture texture) {
object.texture = texture;
}
Note that this is just flow-code. Your code will look different, using byte[] instead of Texture and I don't know if you're using a Button to start the texture-setting. This can be any sort of trigger/starting point.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With