Статьи:Работа с ресурсами

Материал из Blitz3D to Unity3D Wiki Project
Перейти к: навигация, поиск

Вопрос, который довольно быстро встает перед Unity программистом – как загрузить свои ресурсы во время выполнения приложения? В данной статье я бы хотел осветить способы загрузки ресурсов в приложение. Способов несколько:

  1. Загрузка ресурсов, заранее добавленных в проект.
  2. Загрузка внешнего файла с диска.
  3. Загрузка файла из web.
  4. Использование бандлей.

Я не рассматриваю загрузку назначенных на компоненты ресурсов, т.к. они загружаются автоматически при загрузке сцены.

Загрузка ресурсов, заранее добавленных в проект

Данный вид загрузки самый простой, для этого используется функция Resources.Load("путь_до_ресурса", typeof(тип ресурса)). Но прошу обратить внимание на то, что не все ресурсы, добавленные в проект, можно загрузить таким образом. Почему? Потому что Unity добавляет в билд только часть ресурсов, на которые ссылаются компоненты, добавленные объектам сцен. Но эти ресурсы вышеприведенной командой не загрузить, если не соблюдать одно правило: функция Resources.Load загружает только те ресурсы, которые лежат в папке с названием Resources. Причем таких папок в проекте может быть несколько. Сразу оговорюсь, что не стоит все свои ресурсы ложить в эту папку, потому что Unity добавляет в билд все, что вы туда положите. Пример загрузки текстуры, которая лежит по адресу "Textures/Resources/Fruits/Apple.jpg"

Texture2D apple = (Texture2D)Resources.Load("Fruits/Apple", typeof(Texture2D));

Обратите внимание на то, что путь пишется относительно папки Resources и без расширения файла (.jpg). Так же соблюдайте регистр символов.

TextAsset

Есть такой тип ресурсов - TextAsset, который позволяет хранить в проекте текстовые (с расширениями *.txt или *.xml) и бинарные файлы (с расширением *.bytes). Их можно загружать таким же способом:

string text = ((TextAsset)Resources.Load("Texts/text", typeof(TextAsset))).text;

или

byte[] bytes = ((TextAsset)Resources.Load("BinaryData/level01", typeof(TextAsset))).bytes;

Загрузка внешнего файла с диска

Тут приходит на помощь пространство имен System.IO. В котором есть много классов работы с файлами. Например, чтобы загрузить текст из внешнего файла, достаточно использовать класс File и его функцию ReadAllText:

using System.IO;

public void Start()
{
   string text = File.ReadAllText(Application.dataPath+"/Texts/text.txt");
   Debug.Log(text);
}

Обратите внимание на Application.dataPath, это свойство возвращает следующий путь:

  • Unity Editor: <Путь до проекта>/Assets
  • Mac player: <путь до бандля>/Contents
  • iPhone player: <путь до бандля>/<AppName.app>/Data
  • Win player: <путь до исполняемого файла_Data>
  • Web player: Абсолютный url до плеера (без имени unity файла)

Т.е. чтобы прочитать текстовый файл у нас в редакторе должна быть папка Texts и в ней файл text.txt, а если это PC билд под windows, то этот файл должен лежать в папке в папке "путь до исполняемого файла_Data/Texts/"

Еще пример загрузки бинарного файла:

using System.IO;

public void Start()
{
   byte[] bytes = File.ReadAllBytes(Application.dataPath+"/BinaryData/level01.bytes");
   // чтение данных из массива bytes например с использованием MemoryStream и BinaryReader
}

Обратите внимание, что в данном методе загрузки необходим путь до файла с его расширением.

Streaming Assets

Есть так же возможность, чтобы Unity сама копировала файлы при билде. Для этого служит папка с названием StreamingAssets. Любой файл помещенный в такую папку будет автоматически скопирован в папку, зависяшую от платформы: Mac/PC:

path = Application.dataPath + "/StreamingAssets";

iOS:

path = Application.dataPath + "/Raw";

Android:

path = "jar:file://" + Application.dataPath + "!/assets/";

Учтите, что на Andoid файлы хранятся в jar архиве, поэтому для их загрузки потребуется использовать класс WWW

Этот же путь можно получить с помощью свойства Application.streamingAssetsPath

Загрузка файла из web

Тут тоже достаточно просто. Unity предоставляет класс WWW для работы с вэб ресурсами. Например загрузка текстуры могла бы выглядеть так:

using UnityEngine;
using System.Collections;

public class example : MonoBehaviour {
    public string url = "http://headrightgames.com/wp-content/uploads/2011/08/Unity_logo_bg_png_550x4000_upscale_q85-202x202.jpg";
    IEnumerator Start() {
        // начало загрузки
        WWW www = new WWW(url);
        // ожидание завершения
        yield return www;
        // назначаем текстуру текущему материалу объекта
        renderer.material.mainTexture = www.texture;
    }
}

Использование бандлей

В Unity есть возможность создавать архивы с ресурсами - бандли. Но сразу оговорюсь, что воспользоваться ей смогут только владельцы Pro лицензии.

В чем преимущество бандлей?

Бандли позволяют хранить ресурсы в сжатом нативном формате для Unity, что ускоряет их загрузку из Web, кроме того поддерживается асинхронная загрузка ресурсов из бандлей, что позволит подгружать ресурсы не заметно для игрока. Так же бандли позволяют хранить целые сцены, что даст возможность добавлять уровни в игру не пересобирая приложение.

В чем недостатки?

Ну главный недостаток это то, что форматы бандлей под разные платформы различны. Вам например не удастся загрузить в приложение под iOS бандль собранный под Web. Второй недостаток это то, что нет механизма создания бандлей "из коробки". Т.е. бандли можно создавать только с помощью специально написанного скрипта. К счастью в справке по команде BuildPipeline.BuildAssetBundle() есть готовые примеры скриптов, создающих бандли из выделенных объектов.

Загружать бандли можно через WWW, из файла или памяти.

Пример загрузки через WWW:

IEnumerator Start() {
    var www = new WWW ("http://myserver/myBundle.unity3d");
    yield return www;
    // Создание главного ассета бандля.
    Instantiate(www.assetBundle.mainAsset);
}

Чтобы загрузить бандль из памяти надо использовать функцию AssetBundle.CreateFromMemory(), а из файла соответственно AssetBundle.CreateFromFile().


Еще хотел добавить, что загрузка ресурсов в WebPlayer осложняется тем, что плеер может загружать ресурсы только с источников, дающих на это разрешение. Более подробно об этом можете прочитать здесь.