Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Unity_в_действии_Джозеф_Хокинг_Рус.pdf
Скачиваний:
83
Добавлен:
21.06.2022
Размер:
26.33 Mб
Скачать

238      Глава 9. Подключение игры к Интернету

объявленную в момент вызова метода из сценария WebLoadingBillboard. Обратите внимание на синтаксис объявления лямбда-функции: () => {}.

Реализация обратного вызова в виде отдельной функции не только дала возможность вызвать метод в сценарии WebLoadingBillboard; именно лямбда-функция сохраняет локальную копию скачанного изображения. В итоге методу GetWebImage() достаточно скачать изображение один раз; во всех последующих вызовах будет использоваться уже локальная копия.

Так как данная оптимизация применяется к последующим вызовам, ее эффект появится только при наличии нескольких рекламных щитов. Давайте сделаем копию щита, чтобы в сцене появилась хотя бы пара объектов. Выделите щит, выберите команду­ Duplicate (в меню Edit или в меню, вызываемом щелчком правой кнопки мыши) и переместите копию в сторону (например, измените координату X на 18).

Запустите игру и посмотрите, что получилось. В управлении первым щитом отмечается значительная пауза, связанная со скачиванием изображения из Интернета. Зато при подходе ко второму щиту изображение появляется сразу же, ведь оно уже загружено.

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

9.4. Отправка данных на веб-сервер

Мы рассмотрели несколько примеров скачивания данных, но пока ни разу не выполняли обратный процесс. Для выполнения заданий в этом разделе вам потребуется сервер, на который будут отправляться данные. Если возможность доступа к серверу у вас отсутствует, раздел можно просто пропустить. Кроме того, желающие могут легко скачать ПО с открытым исходным кодом и настроить тестовый сервер. Я рекомендую для этой цели сервер XAMPP. Для его скачивания посетите страницу https:// www.apachefriends.org/ru/index.html. После установки у вас появился доступ к папке htdocs с адресом http://localhost/, как будто вы работаете с сервером в Интернете. Со­ здайте в этой папке папку ch9 — именно в ней мы будем сохранять работающие на стороне сервера сценарии.

Вне зависимости от того, с чем вы работаете — с XAMPP или с собственным вебсервером, задача будет одна: отправить на сервер информацию о погоде, как только игрок дойдет до контрольной точки. В качестве такой точки мы поместим в сцену зону триггера, напоминающую дверь из главы 8. Создайте куб, расположите его гденибудь в сторонке, укажите, что его коллайдер используется как триггер, и назначьте ему полупрозрачный материал, как и в предыдущем случае (напоминаю, что вам нужно настроить режим визуализации материала). Итоговый вид этого объекта показан на рис. 9.7.

Теперь, когда в сцене появился триггер, напишем код, который он будет активировать.

Обращение к сценарию на стороне сервера;
при необходимости вы можете его поменять.

9.4. Отправка данных на веб-сервер     239

З а а: , а а

а а а

Рис. 9.7. Контрольная точка, вызывающая отправку данных на сервер

9.4.1. Слежение за погодой: отправка запросов POST

Код, активируемый в контрольной точке, будет последовательно включаться в нескольких сценариях. Как и в случае со скачиванием данных, при отправке данных сценарий WeatherManager заставляет сценарий NetworkService сделать запрос, причем последний полностью отвечает за передачу данных через сеть по протоколу HTTP. Следующий листинг демонстрирует коррективы, которые нужно внести в сценарий

NetworkService.

Листинг 9.17. Сценарий NetworkService с возможностью отправки данных

...

private const string localApi = "http://localhost/ch9/api.php"; ¬

...

private IEnumerator CallAPI(string url, Hashtable args, Action<string>

callback) { ¬ Аргументы, добавленные к параметрам метода CallAPI().

WWW www;

if (args == null) {

www = new WWW(url);

}else {

WWWForm form = new WWWForm(); ¬ Отправляем аргументы вместе с объектом WWW с помощью объекта WWWForm. foreach(DictionaryEntry arg in args) {

form.AddField(arg.Key.ToString(), arg.Value.ToString());

}

www = new WWW(url, form); ¬ Объект WWWForm автоматически меняет запрос с GET на POST.

}

yield return www;

...

}

public IEnumerator GetWeatherXML(Action<string> callback) {

return CallAPI(xmlApi, null, callback); ¬ Вызовы, измененные из-за измененных параметров.

}

public IEnumerator GetWeatherJSON(Action<string> callback) { return CallAPI(jsonApi, null, callback);

}

Отправляем метку времени вместе с информацией об облачности.

240      Глава 9. Подключение игры к Интернету

public IEnumerator LogWeather(string name, float cloudValue, Action<string> callback) {

Hashtable args = new Hashtable(); ¬ Определяем таблицу отправляемых аргументов. args.Add("message", name);

args.Add("cloud_value", cloudValue); args.Add("timestamp", DateTime.UtcNow.Ticks); ¬

return CallAPI(localApi, args, callback);

}

...

Прежде всего обратите внимание на новый параметр метода CallAPI(). Это таблица аргументов, отправляемая вместе с HTTP-запросом. В соответствии с этой таблицей в методе CallAPI() может быть создан объект WWWForm. Обычно объект WWW отправляет запросы GET, а объект WWWForm меняет их на запросы POST. Все остальные изменения в коде вызваны этим основным нововведением (например, модификация кода метода GetWhatever() из-за параметров метода CallAPI()).

Следующий листинг демонстрирует код, который нужно добавить в сценарий

WeatherManager.

Листинг 9.18. Добавление к сценарию WeatherManager кода отправки данных

...

public void LogWeather(string name) { StartCoroutine(_network.LogWeather(name, cloudValue, OnLogged));

}

private void OnLogged(string response) { Debug.Log(response);

}

...

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

Листинг 9.19. Сценарий CheckpointTrigger для зоны триггера

using UnityEngine;

using System.Collections;

public class CheckpointTrigger : MonoBehaviour { public string identifier;

private bool _triggered; ¬ Проверяем, срабатывала ли уже контрольная точка.

void OnTriggerEnter(Collider other) { if (_triggered) {return;}

Managers.Weather.LogWeather(identifier); ¬ Активируем отправку данных. _triggered = true;

}

}