Unity, ECS и все-все-все
Написал статью про ECS в Unity: что это, зачем это и как это работает.
Leopotam провёл редактуру, как автор LeoECS, за что ему — «спасиба» :)
Написал статью про ECS в Unity: что это, зачем это и как это работает.
Leopotam провёл редактуру, как автор LeoECS, за что ему — «спасиба» :)
Обычная линейная интерполяция, но вместо двух точек на входе массив из Vector3. Таким образом можно плавно двигать объект по множеству точек.
Ещё, можно передавать в функцию массив с продолжительностью каждого шага, если необходимо, чтобы объект двигался с разной скоростью от точки к точке.
Если же нужно, чтобы объект пробегал по всем точкам за заданное время, то функцию надо немного поменять и сначала посчитать расстояние между всеми точками.
public IEnumerator Move (Vector3[] positions, float time) {
for (int i = 0; i < positions.Length; i++) {
Vector3 startPosition = transform.position;
float t = 0f;
while (t < 1) {
t += Time.deltaTime / time;
transform.position = Vector3.Lerp (startPosition, positions[i], t);
yield return null;
}
transform.position = positions[i];
}
}
...
Vector3[] positionsArray = { new Vector3 (10f, 10f, 0f), new Vector3 (20f, 20f, 0f), ... };
StartCoroutine (positionsArray, 1f);
Это если не хочется из-за одной функции тянуть левую библиотеку в проект :) А так, DOTween решает наверно все задачи связанные с анимацией объекта.
Почти все последние игры-хиты — многопользовательские. Ведь играть с живыми игроками всегда интереснее — это факт. Но сделать многопользовательскую игру намного сложнее, это тоже очевидно. Мало того, что меняется вся архитектура самого клиента-игры, ещё потребуется сервер, если это онлайн игра. Про некоторые движки онлайн игр, я уже писал.
Также при создании онлайн игры надо будет решить кучу важных моментов: протокол, регистрация и синхронизация игроков, защита от читеров и ботов, лаги, пинг, предсказание, и т. д. И это всё надо учесть как на сервере, так и на клиенте. Да, уже есть готовые фреймворки и онлайн сервисы, где всё это реализовано с примерами клиентов на разных языках и платформах. И в некоторых статьях про это тоже есть.
Ниже небольшая подборка статей и видео, которые ввели меня в курс дела и теперь почти на все эти вопросы, я нашёл ответы.
Как вы комментируете свой код?
Или так: вы комментируете свой код? :)
В своих Unity проектах я использую XML документацию. Это позволяет редактору кода или IDE использовать IntelliSense — всплывающие подсказки, автодополнение кода и т. п.
Для Visual Studio Code есть плагин в маркете C# XML Documentation Comments. Достаточно написать /// (три слеша) и плагин сгенерирует комментарий в нужном формате. Это удобно, это правильно, так надо делать :) В смысле, комментировать код.
Потом, с помощью таких XML комментариев можно сгенерировать документацию всего проекта. Например, с помощью Doxygen. Скармливаем Doxygen папку со скриптами и на выходе получаем что-то такое:
В этом примере, я собрал сразу два интересных момента:
Для чего это может понадобиться? Например, чтобы одна камера была для игры, с настроенными пост эффектами, другая для интерфейса. Или чтобы сделать вот такой эффект размытия. В общем-то, можно и 3 камеры использовать. Зависит от потребностей и фантазии...
Фокус в том, чтобы настроить камеру на рендер только нужного слоя.
Как было сделано в этом примере:
По такому же принципу можно одновременно и 3 камеры сделать. Если потребуется.
Предлагаю тестить и пробовать что-нибудь сделать https://github.com/Leopotam/ecs
Обсуждение на Reddit
Чатик на gitter.im
Подробно на примере другого фреймворка https://habrahabr.ru/post/197920/
Когда-нибудь в 2018 доделают :) Там же и про штатный DI https://www.youtube.com/watch?v=tGmnZdY5Y-E
Когда читаешь форумы и паблики по Unity, часто встречаются вопросы/ответы: как сделать онлайн игру, как сделать мультиплеер, что лучше unet, photon, etc. И часто люди советуют друг другу, как раз решение от самой Unity — UNet или другой вариант — Photon.
Что с одной стороны понять можно — есть документация, примеры, готовый мультиплеер и матчмейкинг, не нужен свой сервер и т. д. Только за это надо платить, когда сервер не твой, то нет полного контроля и гибкости + на тарифе Unity Pro — лимит всего 200 игроков онлайн! У Photon тоже есть ограничения и тоже платная подписная модель. Поэтому если есть вероятность, что игра выстрелит (все же на это надеются :), стоит задуматься о собственном сервере.
Много плюсов в сторону своего сервера и движка. Минимум — это дешевле и есть полный контроль. Из минусов — всё надо настраивать и писать самому. Ну почти всё... Для одинокого разработчика, это может стать проблемой, тем более если нет опыта серверной разработки.
Можно заморочиться, написать клиент и сервер на Unity с использованием UNet и запустить его на своём сервере в режиме Headless Mode. Не пробовал, не знаю.
Написать свой онлайн движок. Или использовать чей-то.
Тут есть место где развернуться, есть много серверных языков и фреймворков. Есть и готовые движки для онлайн игр и ничто не мешает их использовать вместе с Unity. Я рассматривал только Node.js, потому что имел с ним дело и могу разобраться, но уверен, есть и другие, на других языках.
Вот список из нескольких проектов, которые можно взять на изучение и даже что-нибудь на них запустить.
В Google он найдется одним из первых. Написан китайцами, давно не поддерживается и заброшен. Достаточно наворочен и имеет хорошую подробную документацию и примеры, можно расширять плагинами, вообще стоит посмотреть на его архитектуру. Есть готовый клиент для Unity и других платформ.
Этот движок обновляется, последний апдейт был пару недель назад. Позиционируется как движок для HTML5 игр. Работает через вебсокеты, данные сжимаются msgpack, есть встроенный матчмейкинг и компенсация лагов. Хорошая документация и примеры. Есть официальные клиенты на JS, Unity и CoronaSDK.
Уже полгода не обновлялся. Также работает на вебсокетах, есть сжатие, компенсация лагов, предсказание и т. д. Пишут, что подходит для любых игр и жанров. Есть документация и пару примеров на JS.
Для начинающих можно ещё посмотреть эти два репозитория:
https://github.com/bonsaiden/maple.js
https://github.com/huytd/node-js-game-server
Если ещё погуглить, можно найти много примеров на Socket.IO, но мне он почему-то не понравился. Хотя сделать на нём простое онлайн взаимодействие вполне легко.
Меня спрашивали про простой менеджер событий Unity, как передавать разные параметры и количество, а то строки неудобно. В общем-то, это был пример, но если кому-то оказалось нужно — то вот немного улучшенная версия:
using UnityEngine;
using UnityEngine.Events;
using System.Collections.Generic;
using System;
public class EventManager : MonoBehaviour {
[Serializable]
public class GameEvent : UnityEvent<object[]> { };
private static EventManager _instance;
private Dictionary<string, GameEvent> _eventDictionary;
void Awake () {
if (_instance != null)
return;
_instance = GetComponent<EventManager> ();
if (_eventDictionary == null)
_eventDictionary = new Dictionary<string, GameEvent> ();
}
/// <summary>Добавляем "слушателя" для события</summary>
/// <param name="eventName">Название события</param>
/// <param name="listener">Метод-обработчик события</param>
public static void Subscribe (string eventName, UnityAction<object[]> listener) {
GameEvent thisEvent;
if (_instance._eventDictionary.TryGetValue (eventName, out thisEvent))
thisEvent.AddListener (listener);
else {
thisEvent = new GameEvent ();
thisEvent.AddListener (listener);
_instance._eventDictionary.Add (eventName, thisEvent);
}
}
/// <summary>Удаляем "слушателя" из списка</summary>
/// <param name="eventName">Название события</param>
/// <param name="listener">Метод-обработчик события</param>
public static void Unsubscribe (string eventName, UnityAction<object[]> listener) {
if (_instance == null)
return;
GameEvent thisEvent;
if (_instance._eventDictionary.TryGetValue (eventName, out thisEvent))
thisEvent.RemoveListener (listener);
}
/// <summary>Отправить событие</summary>
/// <param name="eventName">Название события</param>
/// <param name="parameters">Параметр массив</param>
public static void SendEvent (string eventName, params object[] parameters) {
GameEvent thisEvent;
if (_instance._eventDictionary.TryGetValue (eventName, out thisEvent)) {
thisEvent.Invoke (parameters);
}
}
}
Теперь количество параметров динамическое и любого типа. Для простого взаимодействия, вполне работоспособно. Пример использования:
void OnEnable () {
EventManager.Subscribe ("event_name", MyFunction);
}
void OnDisable () {
EventManager.Unsubscribe ("event_name", MyFunction);
}
void MyFunction (object[] parameters) {
Debug.Log (parameters.Length); // количество параметров -> 3 в примере
Debug.Log (parameters[1]); // выведет -> 1
}
...
EventManager.SendEvent ("event_name", "param_string", 1, 2); // вызов события
С выходом iPhone X и отказом от физической кнопки Home, Apple доставила некоторые неудобства разработчикам. И хотя для нативных приложений всё прошло более-менее гладко (неадаптированные приложения просто получили черные рамки), то для других — пришлось делать оптимизацию.
Так, в одной из наших игр на Unity, расположение элементов управления находилось в самом нижу экрана, его нужно было поднять вверх, чтобы не задевал Home Indicator. Собственно, с этим никаких проблем не возникло.
Но почему-то в тестах на iPhone 7 с установленной iOS 11.1.1, приложение стало вести себя как-будто это iPhone X — на нижних и верхних гранях экрана перестал работать тач, точнее, он срабатывал, но некорректно. Видимо это баг iOS или Unity, пока не разобрался, но исправить надо было.
Оказывается, можно скрыть Home Indicator и включить т. н. Edge Protection. Это когда первый свайп показывает Home Indicator, а второй скрывает приложение. Пока из коробки Unity не умеет так делать, пишут что в одном из следующих обновлений добавят. В новых версиях добавили в редактор эти функции. Кто на старых версиях 5.5+ (как я), нужно патчить XCode проект. Как это сделать, я уже писал. Раз, два.
Чтобы включить Edge Protection нужно добавить пару строчек кода в два файла:
// UnityViewControllerBaseiOS.h
- (UIRectEdge)preferredScreenEdgesDeferringSystemGestures;
// UnityViewControllerBaseiOS.mm
- (UIRectEdge)preferredScreenEdgesDeferringSystemGestures
{
return UIRectEdgeAll;
}
Все игры с честным, настоящим рандомом, в большинстве случаев будут получать негативные отзывы и оценки игроков.
Это относится к карточным играм, где рандомно карты выдаются, игры с кубиками, игры где случайно выпадают предметы, сундуки и т. п. Игроки всегда будут недовольны настоящим рандомом, будут говорить и писать, что нечестно и подстроено, хотя на самом деле, всё наоборот.
И варианта тут два:
Хотя нет, один вариант — №2. Потому что в итоге, главная цель любой игры — дать удовольствие от игры играющему; выигрывает он, проигрывает — неважно.
Почитать на эту тему: https://gdcuffs.com/post/unfr-rndm/