Reputation: 2684
There are around 10 3D models that I need to load from the server on a button click.
public GameObject DownloadFile(String url)
{
GameObject obj = null;
Debug.Log("url: " + url);
string path = GetFilePath(url);
Debug.Log("Path: " + path);
if (File.Exists(path))
{
Debug.Log("Found file locally, loading...");
Debug.Log(path);
obj = LoadModel(path);
return obj;
}
Debug.Log(path);
StartCoroutine(GetFileRequest(url, (UnityWebRequest req) =>
{
if (req.isNetworkError || req.isHttpError)
{
// Log any errors that may happen
Debug.Log($"{req.error} : {req.downloadHandler.text}");
}
else
{
// Save the model into a new wrapper
obj = LoadModel(path);
obj.SetActive(false);
StopAllCoroutines();
}
}));
return obj;
}
string GetFilePath(string url)
{
filePath = $"{Application.persistentDataPath}/Files/";
string[] pieces = url.Split('/');
string filename = pieces[pieces.Length - 1];
return $"{filePath}{filename}";
}
IEnumerator GetFileRequest(string url, Action<UnityWebRequest> callback)
{
using (UnityWebRequest req = UnityWebRequest.Get(url))
{
req.downloadHandler = new DownloadHandlerFile(GetFilePath(url));
yield return req.SendWebRequest();
callback(req);
}
}
GameObject LoadModel(string path)
{
ResetWrapper();
GameObject model = Importer.LoadFromFile(path);
return model;
}
This is my code right now. I call the DownloadFile function from my script with a URL as a parameter. The Download function returns a null obj because it takes time to download a huge file. So it returns obj without getting downloaded. How do I not make it return until the download is finished?
Upvotes: 0
Views: 112
Reputation: 90649
if you would do what you ask for you would completely freeze your app ... if this is what you want you could of course instead of running a Coroutine simply do
var request = GetFileRequest(url, (UnityWebRequest req) =>
{
if (req.isNetworkError || req.isHttpError)
{
// Log any errors that may happen
Debug.Log($"{req.error} : {req.downloadHandler.text}");
}
else
{
// Save the model into a new wrapper
obj = LoadModel(path);
obj.SetActive(false);
StopAllCoroutines();
}
}
while(request.MoveNext())
{
// freeze
}
return obj;
In most cases however this is absolutely not what you want ;)
Instead of giving it a return type I would rather solve this via a callback:
public void DownloadFile(String url, Action<GameObject> onResult)
{
GameObject obj = null;
Debug.Log("url: " + url);
string path = GetFilePath(url);
Debug.Log("Path: " + path);
if (File.Exists(path))
{
Debug.Log("Found file locally, loading...");
Debug.Log(path);
obj = LoadModel(path);
onResult?.Invoke(obj);
}
Debug.Log(path);
StartCoroutine(GetFileRequest(url, (UnityWebRequest req) =>
{
if (req.isNetworkError || req.isHttpError)
{
// Log any errors that may happen
Debug.LogError($"{req.error} : {req.downloadHandler.text}");
}
else
{
// Save the model into a new wrapper
obj = LoadModel(path);
obj.SetActive(false);
StopAllCoroutines();
onResult?.Invoke(obj);
}
}));
}
So instead of e.g. doing something like
var result = DownloadFile(url);
you would rather do
DownloadFile(url, result => {
// whatever to do with the result object
});
Upvotes: 2