В прошлой части статьи разбирался принцип работы UnityWebRequest с помощью которого проводили загрузку изображения из сети.
Сам по себе UnityWebRequest не выполняет загрузку данных, он нужен лишь для подключения к сети и сетевым ресурсам. Загрузка данных происходит с помощью объекта DownloadHandler, которому посвящена эта часть статьи.
Объект DownloadHandler является базовым классом для работы с массивами данных из сети, он не содержит информацию о том, какие данные в нем хранятся, для этого существуют более специализированные “загрузчики”: DownloadHandlerTexture для загрузки изображений, DownloadHandlerAudioClip для загрузки звуков и т.д. Чаще всего опытные разработчики хранят дополнительные файлы игры в специальных бандлах, похожих на небольшие игровые архивы, которые загружают с помощью DownloadHandlerAssetBundle.
Для того, чтобы лучше понять, как работать с DownloadHandler’ом, разберем простой пример загрузки файла изображения, только в этот раз воспользуемся специальным “загрузчиком” – DownloadHandlerFile, который способен загружать любые файлы из сети. В отличие от предыдущего примера с загрузкой и выведением на экран полученного изображения, в этот раз попробуем загрузить и сохранить файл изображения на ПК.
Создадим новые скрипт RequestFile наследуемый от MonoBehaviour.
- public sealed class RequestFile : MonoBehaviour {
- }
Чуть выше скрипта подключим несколько необходимых библиотек.
- using UnityEngine.Networking;
- using Environment = System.Environment;
- using Path = System.IO.Path;
- public sealed class RequestFile : MonoBehaviour {
- }
Библиотека UnityEngine.Networking содержит в себе все необходимые инструменты для работы с сетью. Следующая библиотека System.Environment необходима, чтобы правильно найти “место”, где будет храниться загруженный файл, и System.IO.Path библиотека которая упростит процесс создания этого “места” на ПК.
Далее в скрипте RequestFile объявим новую строковую переменную url, в которой будет находиться адрес изображения в сети.
- using UnityEngine.Networking;
- using Environment = System.Environment;
- using Path = System.IO.Path;
- public sealed class RequestFile : MonoBehaviour {
- public string url = “”;
- }
В прошлой части статьи, мы уже разбирали, какие типы ссылок можно использовать для загрузки данных из сети. Объявим еще одну строковую переменную fileName, в которой будет указано имя файла, под которым он будет храниться после загрузки.
- using UnityEngine.Networking;
- using Environment = System.Environment;
- using Path = System.IO.Path;
- public sealed class RequestFile : MonoBehaviour {
- public string url = “”;
- public string fileName = “Изображение.jpg”;
- }
Переменная fileName содержит имя файла с его возможным расширением, в данном случае это будет файл формата jpg. Как и прошлом примере, где мы загружали файл через корутину и метод Start, также создаем метод Start в скрипте RequestFile и сделаем из него корутину.
- public sealed class RequestFile : MonoBehaviour {
- public string url = “”;
- public string fileName = “Изображение.jpg”;
- private IEnumerator Start() {
- }
- }
Теперь используя ранее подключенные библиотеки создадим “место”, где будет храниться файл.
- public sealed class RequestFile : MonoBehaviour {
- public string url = “”;
- public string fileName = “Изображение.jpg”;
- private IEnumerator Start() {
- string path = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
- }
- }
Статический метод GetFolderPath класса Environment вернет адрес по которому находится “Рабочий стол” пользователя, так как именно там будет храниться файл. Теперь добавим к полученному адресу “имя” файла под которым он будет храниться, для этого воспользуемся статическим методом Combine класса Path.
- public sealed class RequestFile : MonoBehaviour {
- public string url = “”;
- public string fileName = “Изображение.jpg”;
- private IEnumerator Start() {
- string path = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
- path = Path.Combine(path, fileName);
- }
- }
После того, как путь, по которому будет находится файл готов, можно переходить к его загрузке. Для этого создадим новый экземпляр класса DownloadHandlerFile с адресом, где будет храниться файл и назовем эту переменную loader.
- public sealed class RequestFile : MonoBehaviour {
- public string url = “”;
- public string fileName = “Изображение.jpg”;
- private IEnumerator Start() {
- string path = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
- path = Path.Combine(path, fileName);
- DownloadHandlerFile loader = new DownloadHandlerFile(path);
- }
- }
У класса DownloadHandlerFile есть одно полезное свойство в отличие от других DownloadHandler’ов.
- свойство removeFileOnAbort, которое указывает, что в случае, если файл не удастся загрузить, он будет удален. Полезное свойство, чтобы не хранить неполноценные данные.
- public sealed class RequestFile : MonoBehaviour {
- public string url = “”;
- public string fileName = “Изображение.jpg”;
- private IEnumerator Start() {
- string path = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
- path = Path.Combine(path, fileName);
- DownloadHandlerFile loader = new DownloadHandlerFile(path);
- loader.removeFileOnAbort = true;
- }
- }
Далее необходимо создать UnityWebRequest, который будет выполнять подключение к сетевому ресурсу, где находится загружаемый файл.
- public sealed class RequestFile : MonoBehaviour {
- public string url = “”;
- public string fileName = “Изображение.jpg”;
- private IEnumerator Start() {
- string path = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
- path = Path.Combine(path, fileName);
- DownloadHandlerFile loader = new DownloadHandlerFile(path);
- loader.removeFileOnAbort = true;
- UnityWebRequest r = new UnityWebRequest(this.url);
- }
- }
Как и в прошлом примере, создаем новый экземпляр класса UnityWebRequest, в который передаем ссылку на файл, но в этот раз мы будем отдельно указывать как проводить загрузку файла.
- public sealed class RequestFile : MonoBehaviour {
- public string url = “”;
- public string fileName = “Изображение.jpg”;
- private IEnumerator Start() {
- string path = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
- path = Path.Combine(path, fileName);
- DownloadHandlerFile loader = new DownloadHandlerFile(path);
- loader.removeFileOnAbort = true;
- UnityWebRequest r = new UnityWebRequest(this.url);
- r.downloadHandler = loader;
- }
- }
В свойство downloadHandler класса UnityWebRequest передаем экземпляр класса DownloadHandlerFile.
Важно: все элементы данных по загрузке и работе с сетью являются очень ресурсоемкими, в том числе и UnityWebRequest и DownloadHandler, поэтому необходимо их “вычищать” из памяти, чтобы не засорять её после завершения работы.
- public sealed class RequestFile : MonoBehaviour {
- public string url = “”;
- public string fileName = “Изображение.jpg”;
- private IEnumerator Start() {
- string path = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
- path = Path.Combine(path, fileName);
- DownloadHandlerFile loader = new DownloadHandlerFile(path);
- loader.removeFileOnAbort = true;
- UnityWebRequest r = new UnityWebRequest(this.url);
- r.downloadHandler = loader;
- r.disposeDownloadHandlerOnDispose = true;
- }
- }
Для того, чтобы после завершения загрузки файла, данные выгружались из оперативной памяти, в свойстве disposeDownloadHandlerOnDispose класса UnityWebRequest указываем true, и теперь после сохранения файла, он автоматически выгрузиться из памяти после завершения работы DownloadHandler’а. Далее выполним загрузку данных, для этого воспользуемся новым классом UnityWebRequestAsyncOperation, который помогает отслеживать процесс работы.
- public sealed class RequestFile : MonoBehaviour {
- public string url = “”;
- public string fileName = “Изображение.jpg”;
- private IEnumerator Start() {
- string path = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
- path = Path.Combine(path, fileName);
- DownloadHandlerFile loader = new DownloadHandlerFile(path);
- loader.removeFileOnAbort = true;
- UnityWebRequest r = new UnityWebRequest(this.url);
- r.downloadHandler = loader;
- r.disposeDownloadHandlerOnDispose = true;
- UnityWebRequestAsyncOperation op = r.SendWebRequest();
- yield return op;
- }
- }
Для этого, достаточно в переменную op передать экземпляр класса UnityWebRequestAsyncOperation с помощью метода SendWebRequest класса UnityWebRequest. После чего ожидаем выполнения загрузки файла через корутину. Чтобы после загрузки файла можно было его сразу открыть, воспользуемся методом RevealInFinder класса EditorUtility.
- public sealed class RequestFile : MonoBehaviour {
- public string url = “”;
- public string fileName = “Изображение.jpg”;
- private IEnumerator Start() {
- string path = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
- path = Path.Combine(path, fileName);
- DownloadHandlerFile loader = new DownloadHandlerFile(path);
- loader.removeFileOnAbort = true;
- UnityWebRequest r = new UnityWebRequest(this.url);
- r.downloadHandler = loader;
- r.disposeDownloadHandlerOnDispose = true;
- UnityWebRequestAsyncOperation op = r.SendWebRequest();
- yield return op;
- #if UNITY_EDITOR
- UnityEditor.EditorUtility.RevealInFinder(path);
- #endif
- }
- }
После чего завершаем работу UnityWebRequest’а с помощью метода Dispose.
- public sealed class RequestFile : MonoBehaviour {
- public string url = “”;
- public string fileName = “Изображение.jpg”;
- private IEnumerator Start() {
- string path = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
- path = Path.Combine(path, fileName);
- DownloadHandlerFile loader = new DownloadHandlerFile(path);
- loader.removeFileOnAbort = true;
- UnityWebRequest r = new UnityWebRequest(this.url);
- r.downloadHandler = loader;
- r.disposeDownloadHandlerOnDispose = true;
- UnityWebRequestAsyncOperation op = r.SendWebRequest();
- yield return op;
- #if UNITY_EDITOR
- UnityEditor.EditorUtility.RevealInFinder(path);
- #endif
- r.Dispose();
- }
- }
Чтобы проверить работоспособность скрипта, добавим его на камеру, после чего указываем ссылку на файл в сети и запускаем проект.
Заключение
В этой части статьи мы разобрали разные типы “загрузчиков”, чем они отличаются друг от друга и как с ними работать.