Unity3D:在下载大型 3D 模型文件之前不要继续代码
Unity3D: Don't continue the code until a large 3D model file is downloaded
我需要通过单击按钮从服务器加载大约 10 个 3D 模型。
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;
}
这是我现在的代码。我使用 URL 作为参数从我的脚本调用 DownloadFile 函数。下载函数 return 是一个空对象,因为下载一个大文件需要时间。所以它 returns obj 没有被下载。如何在下载完成后才能return?
如果你按照你的要求去做,你会完全冻结你的应用程序......如果这是你想要的,你当然可以而不是运行协程简单地做
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;
然而,在大多数情况下,这绝对不是您想要的 ;)
与其给它一个 return 类型,我宁愿通过回调来解决这个问题:
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);
}
}));
}
所以而不是例如做类似
的事情
var result = DownloadFile(url);
你更愿意
DownloadFile(url, result => {
// whatever to do with the result object
});
我需要通过单击按钮从服务器加载大约 10 个 3D 模型。
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;
}
这是我现在的代码。我使用 URL 作为参数从我的脚本调用 DownloadFile 函数。下载函数 return 是一个空对象,因为下载一个大文件需要时间。所以它 returns obj 没有被下载。如何在下载完成后才能return?
如果你按照你的要求去做,你会完全冻结你的应用程序......如果这是你想要的,你当然可以而不是运行协程简单地做
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;
然而,在大多数情况下,这绝对不是您想要的 ;)
与其给它一个 return 类型,我宁愿通过回调来解决这个问题:
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);
}
}));
}
所以而不是例如做类似
的事情var result = DownloadFile(url);
你更愿意
DownloadFile(url, result => {
// whatever to do with the result object
});