Unity3D:在下载大型3D模型文件之前,请不要继续执行代码

问题描述

单击一下按钮,需要从服务器加载大约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函数。 Download函数返回一个空obj,因为下载大型文件需要花费时间。因此它返回obj而没有下载。下载完成后如何才能让它返回?

解决方法

如果您要执行请求,则会完全冻结您的应用程序……如果您要这样做,当然可以不用简单地运行Coroutine即可

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;

但是在大​​多数情况下,这绝对不是您想要的;)


我没有给它返回类型,而是希望通过回调来解决这个问题:

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
});