AssetBundle загрузить Crash [duplicate]

Нет стандартного способа сделать это из языка. Я даже не знаю документального расширения, которое может запросить.

Однако некоторые компиляторы имеют опции для установки размера стека. И платформа может указать, что она делает при запуске процесса, и / или предоставить способы установить размер стека нового потока, возможно, даже манипулировать существующим.

Для небольших платформ обычно известно весь размер памяти, все сегменты данных на одном конце, арена с установленным размером для кучи (может быть 0), а остальная часть - стек, приближающийся от другой сторона.

3
задан Programmer 5 June 2018 в 01:14
поделиться

1 ответ

Новый ответ (Unity 2017.2 и выше)

Используйте UnityWebRequest с помощью DownloadHandlerFile . Класс DownloadHandlerFile является новым и используется для загрузки и сохранения файла непосредственно при предотвращении использования высокой памяти.

IEnumerator Start()
{
    string url = "http://dl3.webmfiles.org/big-buck-bunny_trailer.webm";

    string vidSavePath = Path.Combine(Application.persistentDataPath, "Videos");
    vidSavePath = Path.Combine(vidSavePath, "MyVideo.webm");

    //Create Directory if it does not exist
    if (!Directory.Exists(Path.GetDirectoryName(vidSavePath)))
    {
        Directory.CreateDirectory(Path.GetDirectoryName(vidSavePath));
    }

    var uwr = new UnityWebRequest(url);
    uwr.method = UnityWebRequest.kHttpVerbGET;
    var dh = new DownloadHandlerFile(vidSavePath);
    dh.removeFileOnAbort = true;
    uwr.downloadHandler = dh;
    yield return uwr.SendWebRequest();

    if (uwr.isNetworkError || uwr.isHttpError)
        Debug.Log(uwr.error);
    else
        Debug.Log("Download saved to: " + vidSavePath.Replace("/", "\\") + "\r\n" + uwr.error);
}

OLD answer (Unity 2017.1 и ниже) Используйте, если вы хотите получить доступ к каждому байты, когда файл загружается)

. Подобная проблема была вызвана тем, что был создан UnityWebRequest Unity, но он не будет работать напрямую, поскольку API WWW теперь реализован поверх API UnityWebRequest в новейшей версии Unity, что означает, что если вы получите ошибку с API WWW, вы также, вероятно, получите ту же ошибку с UnityWebRequest. Даже если это сработает, у вас наверняка возникнут проблемы с мобильными устройствами с небольшим баром, похожим на Android.

Что нужно сделать, это использовать функцию DownloadHandlerScript UnityWebRequest, которая позволяет вам загружать данные в куски. Загружая данные в куски, вы можете предотвратить возникновение ошибки переполнения. API WWW не реализовал эту функцию, поэтому UnityWebRequest и DownloadHandlerScript должны использоваться для загрузки данных в кусках. Вы можете прочитать, как это работает здесь .

Хотя это должно решить вашу текущую проблему, вы можете столкнуться с другой проблемой памяти при попытке сохранить эти большие данные с помощью File.WriteAllBytes. Используйте FileStream, чтобы выполнить сохранение и закрыть ее только после завершения загрузки.

Создайте пользовательский UnityWebRequest для загрузки данных в виде кусков, как показано ниже:

using System;
using System.IO;
using UnityEngine;
using UnityEngine.Networking;

public class CustomWebRequest : DownloadHandlerScript
{
    // Standard scripted download handler - will allocate memory on each ReceiveData callback
    public CustomWebRequest()
        : base()
    {
    }

    // Pre-allocated scripted download handler
    // Will reuse the supplied byte array to deliver data.
    // Eliminates memory allocation.
    public CustomWebRequest(byte[] buffer)
        : base(buffer)
    {

        Init();
    }

    // Required by DownloadHandler base class. Called when you address the 'bytes' property.
    protected override byte[] GetData() { return null; }

    // Called once per frame when data has been received from the network.
    protected override bool ReceiveData(byte[] byteFromServer, int dataLength)
    {
        if (byteFromServer == null || byteFromServer.Length < 1)
        {
            Debug.Log("CustomWebRequest :: ReceiveData - received a null/empty buffer");
            return false;
        }

        //Write the current data chunk to file
        AppendFile(byteFromServer, dataLength);

        return true;
    }

    //Where to save the video file
    string vidSavePath;
    //The FileStream to save the file
    FileStream fileStream = null;
    //Used to determine if there was an error while opening or saving the file
    bool success;

    void Init()
    {
        vidSavePath = Path.Combine(Application.persistentDataPath, "Videos");
        vidSavePath = Path.Combine(vidSavePath, "MyVideo.webm");


        //Create Directory if it does not exist
        if (!Directory.Exists(Path.GetDirectoryName(vidSavePath)))
        {
            Directory.CreateDirectory(Path.GetDirectoryName(vidSavePath));
        }


        try
        {
            //Open the current file to write to
            fileStream = new FileStream(vidSavePath, FileMode.OpenOrCreate, FileAccess.ReadWrite);
            Debug.Log("File Successfully opened at" + vidSavePath.Replace("/", "\\"));
            success = true;
        }
        catch (Exception e)
        {
            success = false;
            Debug.LogError("Failed to Open File at Dir: " + vidSavePath.Replace("/", "\\") + "\r\n" + e.Message);
        }
    }

    void AppendFile(byte[] buffer, int length)
    {
        if (success)
        {
            try
            {
                //Write the current data to the file
                fileStream.Write(buffer, 0, length);
                Debug.Log("Written data chunk to: " + vidSavePath.Replace("/", "\\"));
            }
            catch (Exception e)
            {
                success = false;
            }
        }
    }

    // Called when all data has been received from the server and delivered via ReceiveData
    protected override void CompleteContent()
    {
        if (success)
            Debug.Log("Done! Saved File to: " + vidSavePath.Replace("/", "\\"));
        else
            Debug.LogError("Failed to Save File to: " + vidSavePath.Replace("/", "\\"));

        //Close filestream
        fileStream.Close();
    }

    // Called when a Content-Length header is received from the server.
    protected override void ReceiveContentLength(int contentLength)
    {
        //Debug.Log(string.Format("CustomWebRequest :: ReceiveContentLength - length {0}", contentLength));
    }
}

Как использовать:

UnityWebRequest webRequest;
//Pre-allocate memory so that this is not done each time data is received
byte[] bytes = new byte[2000];

IEnumerator Start()
{
    string url = "http://dl3.webmfiles.org/big-buck-bunny_trailer.webm";
    webRequest = new UnityWebRequest(url);
    webRequest.downloadHandler = new CustomWebRequest(bytes);
    webRequest.SendWebRequest();
    yield return webRequest;
}
4
ответ дан Programmer 16 August 2018 в 02:24
поделиться
  • 1
    Благодарю. Я внес некоторые изменения, но это решение работает нормально. Спасибо! – ich 5 June 2018 в 01:10
  • 2
    Рад знать, что это сработало для вас – Programmer 5 June 2018 в 01:15
  • 3
    Вы хотите проверить, существует ли файл на сервере перед его сохранением? Это звучит сложно, и я думаю, вы должны создать новый вопрос об этом. Я попытаюсь что-то придумать. – Programmer 8 June 2018 в 01:15
  • 4
    См. Мое изменение в моем ответе. removeFileOnAbort может быть полезна для этого с помощью нового API DownloadHandlerFile. Удачи. – Programmer 8 June 2018 в 02:58
  • 5
    Спасибо, я тестировал новый ответ, он работает хорошо. Спасибо! – ich 11 June 2018 в 03:42
Другие вопросы по тегам:

Похожие вопросы: