В прошлой части статьи мы разбирали, как обрабатывать загружаемые данные из сети с помощью DownloadHandler. В этой части мы попробуем разместить загружаемые файлы на своем собственном сервере. Для этого нам необходимо будет воспользоваться возможностями одного сетевого сервиса – PlayerIO.
PlayerIO – мультиплатформенное сетевое решение для многопользовательских приложений. Данный сервис предлагает свое сетевое API (инструменты) для обеспечения коммуникации игроков через “сервер“, а также базу данных, файловый архив, доступ к социальным сетям и системе внутриигровых покупок.
В этой статье данный сервис будет использоваться только с целью хранения загружаемых файлов на сервере и последующим скачиванием этих самых файлов.
Объем хранилища в бесплатном плане подписки сервиса всего 50 мб.
Для начала необходимо будет зарегистрироваться на этом сервисе, для этого достаточно ввести в любом поисковике слово PlayerIO.
Далее на главной странице необходимо будет создать новый проект игры. Нажимаем MyGames -> CREATE NEW GAME
Задаем имя проекта и нажимаем Create Game.
Готово, новый проект создан.
На главной странице проекта мы видим название проекта и его уникальный сетевой ID, который будем использоваться при подключении к серверу и базе данных.
Далее переходим сразу в раздел GameFS, где будут храниться файлы. Данный раздел находиться слева на главной странице проекта.
Именно здесь можно будет хранить все загружаемые данные: изображения, звуки и даже целые игровые бандлы.
Для загрузки файла можно нажать правой кнопкой мыши в рабочей области и загрузить любой файл нажав Upload Files.
Для примера попробуем загрузить на сервер несколько изображений, чтобы потом можно было их скачать в самой игре в unity.
Теперь, когда проект создан и в нем хранятся файлы для загрузки, можно переходить к технической части.
Сам по себе unity не обладает необходимыми инструментами для подключения к сервису PlayerIO и базе данных разных сетевых сервисов, поэтому нужно будет скачать все необходимые инструменты для работы. Для этого в верхней части сайта PlayerIO нажимаем кнопку SDK.
И переходим по ссылке к загрузке архива со всем необходимым набором API.
Распаковываем архив, из него нам понадобится только папка под названием Untiy3D.
Всю папку переносить в проект нет необходимости, для работы достаточно будет только скопировать один файл – PlayerIOUnity3DClient.dll
Переносим файл PlayerIOUnity3DClient.dll в проект, в специально созданную для таких файлов папку Plugins.
Эта папка специально предназначена для всех подключаемых библиотек в проекте.
Теперь создадим новый скрипт PlayerIORequest наследуемый от MonoBehaviour. В этом скрипте мы будем подключаться к сервису PlayerIO, после чего загружать изображения с сервера с помощью UnityWebRequest.
- public class PlayerIORequest : MonoBehaviour {
- }
Далее подключим все необходимые библиотеки.
- using PlayerIOClient;
- using UnityEngine.Networking;
- public class PlayerIORequest : MonoBehaviour {
- }
Библиотека PlayerIOClient содержит инструменты для работы с сервисом PlayerIO. Следующая библиотека UnityEngine.Networking, которую мы уже разбирали в прошлых частях статьи, необходима для работы с сетью в unity.
Теперь объявим строковую константу в которой будет храниться уникальный ключ. По этому ключу unity сможет подключиться к сервису PlayerIO.
- public class PlayerIORequest : MonoBehaviour {
- private const string ID = “Уникальный ключ”;
- }
Этот уникальный ключ находится в небольшой рамке на главной странице проекта.
Далее объявим новую переменную images, где будет храниться массив загруженных изображения.
- public class PlayerIORequest : MonoBehaviour {
- private const string ID = “Уникальный ключ”;
- private Texture2D[] images = new Texture2D[4];
- }
Так как кол-во загружаемых изображений известно заранее, можно сразу указать размер массива. В данном случае всего 4 файла.
Для подключения к сервису необходимо будет воспользоваться корутиной и одним статическим методом Connect класса PlayerIO. Запишем новый метод Start и преобразуем его в корутину.
- public class PlayerIORequest : MonoBehaviour {
- private const string ID = “Уникальный ключ”;
- private Texture2D[] images = new Texture2D[4];
- private IEnumerator Start() {
- }
- }
Так как подключение через метод Connect происходит асинхронно, для завершения процесса необходимо будет использовать метод-делегат.
- public class PlayerIORequest : MonoBehaviour {
- private const string ID = “Уникальный ключ”;
- private Texture2D[] images = new Texture2D[4];
- private IEnumerator Start() {
- PlayerIO.Connect(ID, “public”, “TestUser”, null, null, OnServerConnected);
- }
- private void OnServerConnected(Client client) {
- }
- }
В метод Connect первым параметром необходимо передать переменную ID в которой храниться уникальный ключ проекта. Второй параметр “public” указывает тип подключения как “публичный”. Третий строковой параметр “TestUser” указывает имя пользователя. Четвертый и пятый параметр можно не указывать, так как они нужны для авторизации. Последним параметром указываем метод-делегат, который выполняется после завершения подключения к сервису.
Метод OnServerConnected принимает только один параметр Client. Экземпляр этого класса нужен для работы с сервисом PlayerIO.
Далее объявим новую переменную client в которой будет находится экземпляр класса Client.
- public class PlayerIORequest : MonoBehaviour {
- private const string ID = “Уникальный ключ”;
- private Texture2D[] images = new Texture2D[4];
- private Client client = null;
- private IEnumerator Start() {
- PlayerIO.Connect(ID, “public”, “TestUser”, null, null, OnServerConnected);
- }
- private void OnServerConnected(Client client) {
- this.client = client;
- }
- }
Теперь, когда подключение к сервису прошло успешно и имеется копия экземпляра класса Client, можно выполнить подключение к серверу, где находятся изображения. Для этого выполним проверку в корутине, о том что подключение выполнено, после чего начнем загружать изображения.
- public class PlayerIORequest : MonoBehaviour {
- private const string ID = “Уникальный ключ”;
- private Texture2D[] images = new Texture2D[4];
- private Client client = null;
- private IEnumerator Start() {
- PlayerIO.Connect(ID, “public”, “TestUser”, null, null, OnServerConnected);
- while(this.client == null) {
- yield return new WaitForEndOfFrame();
- }
- }
- private void OnServerConnected(Client client) {
- this.client = client;
- }
- }
Для проверки воспользуемся циклом while, который будет ожидать завершение подключение к сервису. Далее с помощью цикла получим ссылки на изображения и выполним их загрузку с помощью UnityWebRequest.
- public class PlayerIORequest : MonoBehaviour {
- private const string ID = “Уникальный ключ”;
- private Texture2D[] images = new Texture2D[4];
- private Client client = null;
- private IEnumerator Start() {
- PlayerIO.Connect(ID, “public”, “TestUser”, null, null, OnServerConnected);
- while(this.client == null) {
- yield return new WaitForEndOfFrame();
- }
- string fileName = “Image “;
- string fileExtension = “.jpg”;
- for(int i = 0; i < this.images.Length; i++) {
- }
- }
- private void OnServerConnected(Client client) {
- this.client = client;
- }
- }
В строковой переменной fileName будет храниться имя файла, а в переменной fileExtension, его расширение – в данном случае используется формат jpg.
- private IEnumerator Start() {
- PlayerIO.Connect(ID, “public”, “TestUser”, null, null, OnServerConnected);
- while(this.client == null) {
- yield return new WaitForEndOfFrame();
- }
- string fileName = “Image “;
- string fileExtension = “.jpg”;
- for(int i = 0; i < this.images.Length; i++) {
- string url = “/” + fileName + (i + 1).ToString() + fileExtension;
- url = this.client.GameFS.GetUrl(url);
- }
- }
В цикле объявим новую строковую переменную url, где укажем имя файла который хотим загрузить. После чего с помощью метода GetUrl получим ссылку на файл, который храниться на сервере.
Теперь, получив ссылку на файл можно переходить к его загрузке, для чего создадим новым экземпляр класса UnityWebRequest.
- private IEnumerator Start() {
- PlayerIO.Connect(ID, “public”, “TestUser”, null, null, OnServerConnected);
- while(this.client == null) {
- yield return new WaitForEndOfFrame();
- }
- string fileName = “Image “;
- string fileExtension = “.jpg”;
- for(int i = 0; i < this.images.Length; i++) {
- string url = “/” + fileName + (i + 1).ToString() + fileExtension;
- url = this.client.GameFS.GetUrl(url);
- UnityWebRequest rq = UnityWebRequestTexture.GetTexture(url);
- }
- }
В переменную rq поместим новый экземпляр класса UnityWebRequest со ссылкой на загружаемый файл. Так как загружать мы будем изображения, то можно воспользоваться уже готовым статическим методом GetTexture класса UnityWebRequestTexture, работу с которым мы уже разбирали в предыдущих частях статьи.
Получив ссылку, сразу же начинаем загрузку файла с помощью метода SendWebRequest.
- private IEnumerator Start() {
- PlayerIO.Connect(ID, “public”, “TestUser”, null, null, OnServerConnected);
- while(this.client == null) {
- yield return new WaitForEndOfFrame();
- }
- string fileName = “Image “;
- string fileExtension = “.jpg”;
- for(int i = 0; i < this.images.Length; i++) {
- string url = “/” + fileName + (i + 1).ToString() + fileExtension;
- url = this.client.GameFS.GetUrl(url);
- UnityWebRequest rq = UnityWebRequestTexture.GetTexture(url);
- rq.SendWebRequest();
- while(rq.isDone == false) {
- yield return new WaitForEndOfFrame();
- }
- }
- }
После ожидания выполнения загрузки с помощью условия isDone, попробуем получить изображение через DownloadHandlerTexture и поместить ее в массив.
- private IEnumerator Start() {
- PlayerIO.Connect(ID, “public”, “TestUser”, null, null, OnServerConnected);
- while(this.client == null) {
- yield return new WaitForEndOfFrame();
- }
- string fileName = “Image “;
- string fileExtension = “.jpg”;
- for(int i = 0; i < this.images.Length; i++) {
- string url = “/” + fileName + (i + 1).ToString() + fileExtension;
- url = this.client.GameFS.GetUrl(url);
- UnityWebRequest rq = UnityWebRequestTexture.GetTexture(url);
- rq.SendWebRequest();
- while(rq.isDone == false) {
- yield return new WaitForEndOfFrame();
- }
- Texture2D image = DownloadHandlerTexture.GetContent(rq);
- if (image != null) {
- this.images[i] = image;
- }
- }
- }
Статический метод GetContent класса DownloadHandlerTexture, вернет полученное изображение, после чего проверяем файл на его “целостность” и помещаем в массив images.
После выполнения загрузки всех указанных файлов, попробуем вывести их через стандартный GUI на экран, для этого воспользуемся методом OnGUI.
- public class PlayerIORequest : MonoBehaviour {
- private const string ID = “Уникальный ключ”;
- private Texture2D[] images = new Texture2D[4];
- private Client client = null;
- /*Остальной код*/
- private void OnGUI() {
- for(int i = 0; i < this.images.Length; i++) {
- Texture2D image = this.images[i];
- }
- }
- }
В методе OnGUI, с помощью цикла выведем каждое полученное изображение.
- public class PlayerIORequest : MonoBehaviour {
- private const string ID = “Уникальный ключ”;
- private Texture2D[] images = new Texture2D[4];
- private Client client = null;
- /*Остальной код*/
- private void OnGUI() {
- for(int i = 0; i < this.images.Length; i++) {
- Texture2D image = this.images[i];
- float x = i * 200f;
- Rect rect = new Rect(x, 0, 200f, 200f);
- if (image != null) {
- GUI.DrawTexture(rect, image);
- }
- }
- }
- }
После чего можно запустить проект и посмотреть на результат.
Заключение
С помощью таких сервисов по типу PlayerIO, можно организовывать хранение сторонних игровых файлов и загружать их из сети когда необходимо. Исходный проект можно скачать отсюда