Создание игры на Unity небольшой командой: особенности технологии.

В первой главе вы найдете основную информацию по загрузке и установке Unity и подготовке первой сцены нашей игры.

Настройка среды в Unity

Начнем с самого простого: загрузки и настройки Unity .

Загрузите последнюю версию с официального сайта или торрента и запустите установочный файл.

Для редактирования кода в Unity (4.0.1 и выше) служит редактор MonoDevelop. Если вы работаете в Windows, вы можете (и я вам советую) использовать альтернативый редактор Visual Studio 2013 Desktop (C#) для Windows , после чего в настройках Unity измените редактор по умолчанию на Visual Studio.

Полезно знать: невозможно использовать отладчик Visual Studio 2013 Express с Unity. Вы должны иметь Pro версию Visual Studio и купить UnityVS плагин. С версией Express, вы будете иметь лучший редактор кода, но отсутствие отладчика сведет на нет все его достоинства.

Mac OS X

Заметка о папке Resources : если вы уже работали с Unity, вы знает, что Resources – полезная и уникальная папка. Она позволяет загрузить в скрипт объект или файл (с помощью статичного класса Resources). Она понадобится нам в самом конце (в главе, посвященной меню). Проще говоря, пока мы не будем ее добавлять.

Наша первая игровая сцена

Панель Hierarchy (Иерархия) содержит все объекты, которые доступны в сцене. Это то, чем вы манипулируете, когда начинаете игру с помощью кнопки "Play".

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


Как вы можете видеть здесь, у нас здесь 3 потомка для объекта Level .

В Unity можно создать пустой объект и использовать его в качестве "папки" для других игровых объектов. Это упростит структуру вашей сцены.

Убедитесь, что все они имеют координаты (0, 0, 0) и тогда вы сможете легко их найти! Пустые объекты никак не используют свои координаты, но они влияют на относительные координаты их потомков. Мы не будем говорить об этой теме в этом уроке, давайте просто обнулим координаты ныших пустых объектов.

Заполнение сцены

По умолчанию, новая сцена создается с объектом Main Camera (Главная камера). Перетащите ее на сцену.

Для начала создайте эти пустые объекты:

Scripts Мы добавим наши скрипты сюда. Мы используем этот объект, чтобы прикрепить сценарии, которые не связаны с объектом – например, скрипт гейм-менеджера. Render Здесь будет наша камера и источники света. Level

В Level создайте 3 пустых объекта:

  • 0 - Background
  • 1 - Middleground
  • 2 - Foreground

Сохраните сцену в папке Scenes . Назовите ее как угодно, например Stage1 . Вот, что у нас получилось:

Совет: по умолчанию игровой объект привязан к положению родителя. Это приводит к интересному побочному эффекту при использовании объекта камеры: если камера является дочерним объектом, она автоматически будет отслеживать положение родителя. Если же она является корневым объектом сцены или находится внутри пустого игрового объекта, она всегда показывает один и тот же вид. Однако если вы поместите камеру в движущийся игровой объект, она будет следовать за его передвижениями в пределах сцены. В данном случае нам нужна фиксированная камера, поэтому мы помещаем ее в пустой объект Render . Но запомните это свойство объекта камеры, оно может вам пригодиться. Мы подробно остановимся на этой теме в главе "Паралаксный скроллинг".

Мы только что создали базовую структуру нашей игры. На следующем этапе мы начнем делать забавные вещи: добавим на сцену фон и кое-что еще!

Добавляем фон в сцену

Наш первый фон будет статическим. Воспользуемся следующим изображением:


Импортируйте изображение в папку Textures (Текстуры). Просто скопируйте файл в нее, или перетащите его из проводника. Не беспокойтесь сейчас о настройках импорта.

Создайте в Unity новый игровой объект Sprite на сцене.

Что такое спрайт?

По сути, спрайт – это 2D-изображение, используемое в видео-игре. В данном случае это объект Unity для создания 2D-игр.

Добавляем текстуру спрайта

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


Вы должны нажать на маленький круглый значок справа от поля ввода, чтобы появилось Select Sprite (Выбрать спрайт) в Инспекторе

Мой спрайт не появляется в диалоговом окне! Убедитесь, что вы находитесь в вкдадке Assets диалогового окна "Select Sprite" (Выбрать спрайт). Если вы видите диалоговое окно пустым, - не пугайтечсь. Дело в том, что для некоторых установок Unity, даже со свежим новым 2D проектом изображения импортируются как "Текстура", а не "Спрайт". Чтобы это исправить, необходимо выбрать изображение на панели "Проект", и в "Инспекторе", изменить свойство "Текстура Type" имущество "Sprite":

Итак, мы создали простой спрайт отображающий облака на небе. Давайте внесем изменения в сцену. В панели Hierarchy (Иерархия) выберите New Sprite . Переименуйте его в Background1 или что-то такое, что легко запомнить. Переименуйте его в Background1 или что-то такое, что легко запомнить. Затем переместите объект в нужное место: Level -> 0 - Background . Измените координаты на (0, 0, 0) .


Создайте копию фона и поместите его в (20, 0, 0) . Это должно отлично подойти к первой части.

Tip : Вы можете создать копию объекта с помощью клавиш cmd + D в OS X или ctrl + D Windows .

Слои со спрайтами

Следующее утверждение очевидно, но обладает некими неудобствами: мы отображения 2D мир. Это означает, что все изображения на одной и той же глубине, то есть 0 . И вы графический движок не знает, что отображать в первую очередь. Слои спрайтов позволяют нам обозначить, что находится спереди, а что сзади.

В Unity мы можем изменить "Z" наших элементов, что позволит нам работать со слоями. Это то, что мы делали в этом руководстве перед обновлением до Unity 5, но нам понравилась идея идея использовать слои со спрайтами. У вашего компонента Sprite Renderer есть поле с именем Sorting Layer с дефолтным значением. Если щелкнуть на нем, то вы увидите:

Давайте добавим несколько слоев под наши нужды (используйте кнопку +):

Добавьте фоновый слой к вашему спрайту фона:

Настройка Order in Layer - это способ ограничить подслои. Спрайты с меньшим номером оказываются перед спрайтами с большими числами.

Слой Default нельзя удалить, так как это слой, используемый 3D-элементами. Вы можете иметь 3D-объекты в 2D игре, в частности, частицы рассматриваются как 3D-объекты Unity, так что они будут рендериться на этом слое.

Добавление элементов фона

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


Как видите, мы поместили две платформы в один файл. Это хороший способ научиться обрезать спрайты с помощью новых инструментов Unity .

Получение двух спрайтов из одного изображения

Выполняйте следующие действия:

  1. Импортируйте изображения в папку "Текстуры"
  2. Выберите спрайт Platform и перейдите к панели Инспектор
  3. Измените "Sprite Mode" на "Multiple"
  4. Нажмите на кнопку Sprite Editor (Редактор спрайта)

В новом окне (Sprite Editor) вы можете рисовать прямоугольники вокруг каждой платформы, чтобы разрезать текстуру на более мелкие части:


Кнопка Slice в левом верхнем углу позволит вам быстро и автоматически проделать эту утомительную работу:

Unity найдет объекты внутри изображения и будет нарежет их автоматически. Вы можете установить дефолтное значение для точки вращения или минимальный размер каждого фрагмента. Для простого изображения без артефактов, это необычайно эффективно. Тем не менее, если вы используете этот инструмент, будьте осторожны и проверьте результат, чтобы убедиться, что вы получили то, что хотели.

В этом уроке проделаем эту операцию вручную. Назовите платформы platform1 и platform2 . Теперь, под файлом изображения, вы должны увидеть два спрайта отдельно:


Добавим их в сцену. Для этого мы будем выполнять те же действия что и для фона: создадим новый спрайт и выберим platform1 . Потом повторим эти действия для platform2 . Поместите их в объект 1 - Middleground . Убедитесь, что их позиция по оси Z равна нулю.


Prefabs (Префабы)


Таким образом вы создадите Prefab , точно отвечающий оригинальному игровому объекту. Вы увидите, что игровой объект, который вы конвертировали в Prefab , представляет собой новый ряд кнопок прямо под его именем:


Заметка о кнопках "Prefab": При последующей модификации игрового объекта, вы можете использовать кнопку "Apply", чтобы применить эти изменения к Prefab , или кнопку "Revert", чтобы отменить все изменения игрового объекта в свойстваъ Prefab . Кнопка "Select" переместит выбранные свойства в ассет Prefab в окне проекта (они будут выделены).

Создание префабов с объектами-платформами упростит их повторное использование. Просто перетащите Prefab на сцену, чтобы добавить копию. Попробуйте добавить другую платформу таким же образом.

Теперь вы можете добавить больше платформ, меняющих свои координаты, размеры и плоскости (вы можете поместить их на заднем или переднем плане, просто установите координату Z для платформы на 0).

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

Слои

Прежде чем двигаться дальше, мы модифицируем наши слои, чтобы избежать каких-либо проблем с порядком их отображения. Для этого просто измените позицию игровых объектов по оси Z во вкладке Hierarchy (Иерархия) следующим образом:

При переключении из 2D режима в 3D, в окне "Scene" (Сцена) вы будете четко видеть слои:


Кликнув на игровом объекте Main Camera , вы увидите, что флажок Projection установлен на Orthographic . Эта настройка позволяет камере визуализировать 2D игру без учета трехмерных свойств объектов. Имейте в виду, что даже если вы работаете с 2D объектами, Unity по-прежнему использует свой 3D движок для визуализации сцены. Рисунок выше это наглядно демонстрирует.

В следующем уроке:

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

Наткнулся на англоязычную статью 2012-го года, от немецкого автора, фрилансера-геймдевелопера, разработчика инструментов для Юнити — Herman Tulleken. В статье, сведены 50 советов по работе в Юнити. Советы основаны на опыте работы автора в проектах, с командами от 3 до 20 человек. Автор предупреждает, что не все из них, могут быть применены в каждом проекте; многие советы — дело вкуса. От себя добавлю, что Юнити эти 3 года не стоял на месте, и возможно некоторые советы, могут быть уже не актуальны. Перевода я не нашел. Подумал, а почему бы мне ее не перевести ее, для своего сайта.

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

Процесс

1. Избегайте разветвленных ассетов. Всегда, должна быть только одна версия, любого ассета. Если вам абсолютно необходимо ответвить новую версию префаба, сцены или сетки, следуйте процессу, это сделает ясным, какая версия является правильной. «Неправильная» версия должна иметь броское имя, например, использовать двойное подчеркивание префикс: __MainScene_Backup . Ветвление префабов требует определенного процесса, чтобы сделать его безопасным (см в разделе Префабы).

2. Каждый член команды, должен иметь второй экземпляр проекта для тестирования, если вы используете систему контроля версий. Все изменения должны делаться, и тестироваться в нём, и затем вносится в «чистовую» версию. Никто не должен делать какие-либо изменения в их «чистовых» экземплярах. Это особенно полезно, чтобы отловить недостающие ассеты.

3. Рассмотрите возможность использования внешних инструментов для редактирования уровня. Юнити не лучший инструмент для этого. Например, мы использовали TuDee для создания уровней на основе 3D-тайлов, где есть такие полезные функции, как: привязка к сетке, 2D вид, быстрый выбор тайлов. Простое инстанцирование префабов из XML-файлов.

4. Рассмотрите сохранение уровней в XML, а не в сценах. Это прекрасный метод:

  • это избавляет от необходимости настраивать каждую сцену;
  • это делает загрузку намного быстрее (если большинство объектов являются общими для всех сцен).
  • это делает легче объединение сцен.
  • это делает более легким отслеживание данных уровня.

Вы по-прежнему сможете использовать Unity в качестве редактора уровня (хотя и не должны). Вам нужно будет написать код для сериализации и десериализации данных, для загрузки уровня в редакторе и во время выполнения, а также для сохранения уровня в редакторе. Вам также может понадобиться, имитировать ID систему Unity, для поддержания ссылок между объектами.

5. Рассмотрите написание пользовательского инспектора. Написать пользовательский инспектор довольно просто, но система Unity имеет много недостатков:

  • Он не позволяет воспользоваться преимуществами наследования.
  • Он не позволяет определить компоненты инспектора на уровне поля, только на уровне класса. Например, если каждый игровой объект, имеет поле типа SomeCoolType , который вы хотите отобразить в инспекторе иначе, вы должны написать инспектор для каждого класса.

Вы можете решить эти вопросы, повторной реализацией системы инспекторов. Используя несколько приемов рефлексии, это не так сложно, как кажется. Детали, представлены в конце статьи.

Организация сцены

6. Используйте именованные пустые объекты, как папки. Тщательно организовывайте свои сцены, чтоб облегчить поиск объектов в них.

7. Помещайте при редактировании свои префабы и папки (пустышки) в нулевые координаты (0, 0, 0). Если префаб/пустышка редактируется не для позиционирования, он должен быть в нуле. Таким образом, уменьшается вероятность возникновения проблем с локальными и мировыми системами координат, и код как правило проще.

8. Минимизируйте использование смещений для компонентов GUI. Смещения должны использоваться для компоновки компонентов, только относительно их родительского контейнера; они не должны полагаться на позиционирование своих прародителей. Смещения не должны отменять друг друга, чтобы правильно отображаться. Это в основном для предотвращения такого рода вещей:

Родительский контейнер произвольно размещен в (100, -50). Ребенок, предназначенный для позиционирования в точке (10, 10), помещен в (90, 60) [относительно родительского].

Эта ошибка распространена, когда контейнер невидим, или не имеет визуального представления вообще.

9. Размещайте вашу землю на y=0. Это облегчает задачу размещение объектов на земле.

10. Делайте игру, готовую к запуску в каждой сцене. Это значительно сокращает этап тестирования. Для этого нужно сделать 2 вещи:

Во-первых, предоставить в сцене все данные, требующиеся от предшествующих сцен, если они не доступны.

Во-вторых, создайте объекты, которые должны сохраняться между загрузками сцены, следующим образом:

myObject = FindMyObjectInScene();

if (myObjet == null)
{
myObject = SpawnMyObject();
}

Арт

11. Размещайте пивот поинты (точки вращения) в основании объектов и персонажей, а не в центре. Это упрощает установку объектов, точно на поверхность. Так же это позволяет работать с 3d, как с 2d в игровой логике, AI, и даже в физике, когда это необходимо.

12. Ориентируйте все ваши объекты, включая персонажей, «лицом» вдоль одной и той же оси (положительное или отрицательное направление оси Z). Многие алгоритмы упрощаются, когда все объекты лицом направлены в одном направлении. Тут имеются ввиду, локальные оси самого объекта, а не мировые.

13. Позаботьтесь о правильном масштабе своих ассетов, до импорта в движок. При масштабе (1, 1, 1) они должны иметь задуманные размеры. Для сравнения, можно использовать ссылку на объект куба в юнити, находящийся в стандартных ассетах. Выберите подходящее соотношения к мировым единицам, и придерживайтесь его.

14. Чтобы, было легче размещать и ориентировать GUI и партиклы, используйте two-poly plane (плоскость из двух треугольников). Сориентируйте плоскость лицом по оси Z (см. пункт 12) и вкладывайте в нее GUI или партиклы.

15. Создайте и применяйте тестовые арты:

  • Меченые квадраты для скайбоксов.
  • Текстуру с сеткой.
  • Различные «плоские» цвета для шейдерного тестирования: белый; черный; 50% серого; красный; зеленый; синий; пурпурный; желтый; голубой.
  • Градиенты для шейдерного тестирования: от черного к белом; от красного к зеленому; от красного к синему; от зеленого к синему.
  • Текстуру «чекер» (черно-белые квадраты, по типу шахматной доски).
  • Сглаженные и жесткие карты нормалей.
  • Готовое и настроенное освещение, для быстрого создания тестовых сцен.

Префабы

16. Используйте префабы абсолютно для всего. Единственные объекты, которые не должны быть префабом, это папки. Даже уникальные объекты, которые будут использованы только раз, должны быть префабом. Это облегчает внесение изменений в сцены, не трогая сами сцены. (Дополнительным преимуществом является то, что это делает построение атласа спрайтов надежнее, при использовании EZGUI).

17. Используйте отдельные префабы для специализации, не специализируйте экземпляры. Например, если у вас 2 типа врагов, отличающихся друг от друга только свойствами, сделайте отдельный префаб для этих свойств и свяжите их. Это позволит:

  • вносить изменения для каждого типа в одном месте;
  • вносить изменения без изменения сцены.

Если у вас слишком много типов врагов, экземпляры все равно не нужно делать в редакторе. Как вариант, можно сделать это процедурно, или используя файл/префаб для всех врагов. А конкретный тип определять через выпадающее меню, или алгоритм на основе вражеской позиции, или прогресса игрока.

18. Связывайте префабы с префабами; не связывайте экземпляры с экземплярами. Ссылки на префаб поддерживаются, при помещении префаба в сцене; ссылки на экземпляры нет. Ссылки на префабы, когда это возможно, упрощают настройку сцены, и уменьшают необходимость ее изменения.

19. Насколько это, возможно, устанавливайте связи между экземплярами автоматически. Если вам необходимо установить связь между экземплярами, делайте это программно (в коде). Например, префаб игрока может зарегистрировать себя в GameManager , когда он стартует. Или GameManager может сам найти экземпляр префаба игрока, когда он стартует.

Не ставьте меши, в корень префаба, если собираетесь добавлять другие скрипты. Когда вы делаете префаб из меша, поместите его в пустой объект, сделав, таким образом, корнем пустышку, и уже на нее вешайте скрипты. Так намного проще заменить меш другим мешем, не потеряв каких-то значений, которые вы установили в инспекторе.

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

20. Используйте безопасный процесс ветвления префабов. Объясним на примере префаба Player .

Делать опасные изменения в префабе, нужно следующим образом:

  • Скопировать префаб Player .
  • Переименовать дубликат на __Player_Backup .
  • Сделайте изменения в префабе Player .
  • Если все работает, удалить __Player_Backup .

Не называйте дубликат Player_New , и не вносите в него изменения!

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

Разработчик 1:

  • Скопировать префаб Player .
  • Переименовать его в __Player_WithNewFeature или __Player_ForDev .
  • Сделать изменения в дубликате, закоммитить / передать 2-му разработчику.

Разработчик 2:

  • Внести изменения в новый префаб.
  • Скопировать префаб Player , и назвать его __Player_Backup .
  • Перетащить экземпляр __Player_WithNewFeature на сцену.
  • Перетащите экземпляр на оригинальный префаб Player .
  • Если все работает, удалить __Player_Backup и __Player_WithNewFeature .

Расширения и MonoBehaviourBase

21. Расширьте MonoBehaviour своим поведением, и получайте все ваши компоненты от него. Это позволяет реализовать некоторую общую функциональность, такие как типобезопасного вызова (Invoke), и более сложные вызовы (например, случайный, и т.д.).

22. Определите безопасные методы для методов Invoke, StartCoroutine и Instantiate. Определите делегат Task, и используйте его, для определения методов, которые не зависят от имени. Например:

public void Invoke(Task task, float time)
{
Invoke(task.Method.Name, time);
}

23. Используйте расширения для работы с компонентами, которые наследуют интерфейс. Иногда это удобно, для получения компонентов, реализующих определенный интерфейс, или для поиска объектов с такими компонентами.

Реализации ниже используют TypeOf , вместо обобщенных версий этих функций. Обобщенные версии не работают с интерфейсами. Методы ниже, обертывают TypeOf-версии в обобщенные методы.

//Defined in the common base class for all mono behaviours
public I GetInterfaceComponent() where I: class
{
return GetComponent(typeof(I)) as I;
}

Public static List FindObjectsOfInterface() where I: class
{
MonoBehaviour monoBehaviours = FindObjectsOfType();
List list = new List();

Foreach(MonoBehaviour behaviour in monoBehaviours)
{
I component = behaviour.GetComponent(typeof(I)) as I;

If(component != null)
{
list.Add(component);
}
}

Return list;
}

24. Используйте расширения, чтобы сделать синтаксис более удобным. Например:

public static class CSTransform
{
public static void SetX(this Transform transform, float x)
{
Vector3 newPosition =
new Vector3(x, transform.position.y, transform.position.z);

Transform.position = newPosition;
}
...
}

25. Используйте безопасную альтернативу GetComponent. Иногда внедрение зависимостей компонентов (через RequiredComponent ), может быть болезненным. Например, это затрудняет изменение компонентов в инспекторе (даже, если они имеют тот же базовый тип). В качестве альтернативы, может быть использовано, следующее расширение GameObject , для вывода ошибки, если компонент не найден.

public static T GetSafeComponent(this GameObject obj) where T: MonoBehaviour
{
T component = obj.GetComponent();

If(component == null)
{
Debug.LogError("Expected to find component of type "
+ typeof(T) + " but found none", obj);
}

Return component;
}

Идиомы

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

  • Некоторые идиомы не сочетаются.
  • Использование одной и той же идиомы, помогает всей команде понять, что происходит. Это делает структуру и код легче для понимания. Уменьшает вероятность совершить ошибку.

Примеры групп идиом:

  • Сопрограммы vs конечного автомата.
  • Вложенные префабы vs связанные префабы vs «Бог»-префабы.
  • Стратегии разделения данных.
  • Способы использования спрайтов для состояний в 2D-игр.
  • Структура префаба.
  • Стратегии спауна (spawning).
  • Способы поиска объектов: по типу vs по имени vs по тегу vs по слою vs ссылке.
  • Способы группировки объектов: по типу vs по имени vs по тегу vs по слою vs массиву или ссылкам.
  • Поиск групп объектов vs self-registration.
  • Контроль порядка выполнения (использовать установленный порядок исполнения Unity vs логику yield vs Awake/Start и Update/Late Update vs ручные методы vs в любом порядке).
  • Выделение объектов / позиции / целей с помощью мыши в игре: менеджер выделения vs локальный self-management.
  • Хранение данных между изменениями сцены: через PlayerPrefs, или объекты, которые не уничтожаются при загрузке новой сцены.
  • Способы комбинирования (смешивания, добавления и наслаивание) анимации.

(*vs — против)

Время

27. Держите свой собственный класс времени, чтобы сделать паузу легче. Оберните Time.DeltaTime и Time.TimeSinceLevelLoad для учета пауз и временной шкалы. Использование его требует дисциплины, но облегчит работу с разными таймерами (например, анимация интерфейса и игровая анимация).

Спаун объектов

28. Не позволяйте порождаемым объектам загромождать иерархию, когда игра запущена. Установите для них родителя — объект сцены, для облегчения поиска объектов, при запущенной игре. Вы можете воспользоваться пустым объектом игры, или даже единичным объектом без поведения, чтобы легко получить доступ из кода. Вызовите этот объект DynamicObjects .

Дизайн классов

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

public class Singleton : MonoBehaviour where T: MonoBehaviour
{
protected static T instance;

/**
Returns the instance of this singleton.
*/
public static T Instance
{
get
{
if(instance == null)
{
instance = (T) FindObjectOfType(typeof(T));

If (instance == null)
{
Debug.LogError("An instance of " + typeof(T) +
" is needed in the scene, but there is none.");
}
}

Return instance;
}
}
}

Синглтоны полезны, для различных менеджеров, таких как ParticleManager , или AudioManager , или GUIManager .

  • Избегайте использования синглтонов для уникальных экземпляров префабов, которые не менеджеры (например, экземпляр Игрока). Не соблюдение этого принципа, усложняет иерархию наследований, и делает некоторые изменения сложнее. Вместо этого, держите ссылки на такие экземпляры в вашем GameManager (или другом подходящем «Бог»-классе;-)).
  • Определите статические свойства и методы для публичных переменных и методов, которые часто используются за пределами класса. Это позволит вам писать GameManager.Player вместо GameManager.Instance.player .

30. Для компонентов, никогда не делайте переменные общедоступными, если они не должны изменяться через инспектор. Иначе, ее может «покрутить» дизайнер, не зная, что переменная делает. В редких случаях, это неизбежно. В таком случае, используйте два, или даже четыре подчеркивания в качестве префикса, в имени переменной, чтобы отпугнуть «крутильщиков»:

public float __aVariable;

31. Отделяйте интерфейс от логики игры. Это, по сути паттерн MVC.

Каждый контроллер ввода, должен лишь давать команды соответствующим компонентам, чтобы дать им знать, что контроллер был вызван. Например, в логике контроллера, можно решать, какие команды давать, основываясь на состоянии игрока. Но это плохо (например, это приведет к дублированию логики, если добавлено несколько контроллеров). Вместо этого, объект Игрока должен быть уведомлен о намерениях двигаться вперед, а затем на основе текущего состояния (замедлен или оглушен, например) установить скорость и обновить направление игрока. Контроллеры должны делать только то, что относится к их собственному состоянию (контроллер не меняет состояние, когда игрок изменяет состояние, поэтому контроллер вообще не должен знать о состоянии игрока). Другим примером является смена оружия игроком. Правильный способ сделать это в Player , с помощью метода SwitchWeapon(Weapon newWeapon) , который можно вызвать из GUI. GUI не должен манипулировать трансформациями, родителями и т.д..

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

Объекты геймплея не должны знать практически ничего о GUI. Единственным исключением является режим паузы, которая может контролироваться глобально посредством Time.timeScale (что не является хорошей идеей). Геймплейные объекты должны знать, если игра приостановлена. И это всё. Поэтому, не должно быть ссылок, на GUI-компоненты из объектов геймплея.

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

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

32. Разделяйте состояние игры и промежуточные данные. Промежуточные данные используются для скорости или удобства, и могут быть извлечены из состояния. Делая такое разделение, вы упрощаете:

  • сохранение состояния игры
  • отладку состояния игры

Один из способов сделать это, определение класса SaveData для каждого класса игровой логики:


PlayerSaveData
{
public float health; //public for serialisation, not exposed in inspector
}

Player
{
//... bookkeeping variables (переменные промежуточных данных)

//Don’t expose state in inspector. State is not tweakable.
private PlayerSaveData playerSaveData;
}

33. Отделяйте конфигурацию специализаций.

Рассмотрим на примере двух врагов с одинаковыми мешами, но с разными настройками экземпляров (например, разные сила и скорость). Есть разные пути разделить данные. Вот один из тех, что я предпочитаю, особенно когда объекты порождены, или игра сохранена. (Настройки объектов не являются состоянием, это конфигурационные данные, так что они не должны сохраняться. Когда объект загружен, или порожден, конфигурационные данные, загружаются отдельно автоматически.)

  • Определите шаблонный класс для каждого класса игровой логики. Для экземпляра врага, мы определим класс EnemyTemplate . Где будут храниться, все отличительные характеристики.
  • В классе игровой логики, определите переменную типа нашего шаблона.
  • Сделайте префаб врага, и два шаблонных префаба WeakEnemyTemplate и StrongEnemyTemplate .
  • При загрузке и порождении объектов, задайте переменной шаблона нужный шаблон.

Этот метод может стать довольно сложным (а иногда, излишне сложным, так что будьте осторожны!).

Например, лучше будет использование полиморфизма обобщения, мы можем определить класс, так:

public class BaseTemplate
{
...
}

Public class ActorTemplate: BaseTemplate
{
...
}

Public class Entity where EntityTemplateType: BaseTemplate
{
EntityTemplateType template;
...
}

Public class Actor: Entity
{
...
}

34. Не используйте строки ни для чего, кроме отображаемого текста. В частности, не используйте строки для идентификации объектов, префабов и т.д.. Досадным исключением является анимация, доступ к которым осуществляется по строковым именам.

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

public void SelectWeapon(int index)
{
currentWeaponIndex = index;
Player.SwitchWeapon(weapons);
}

Public void Shoot()
{
Fire(bullets);
FireParticles(particles);
}

Проблема тут не столько в коде, сколько в безошибочных настройках в инспекторе.
Вместо этого определите класс, который инкапсулирует три переменные, и создайте упомянутый массив, вот так:


public class Weapon
{
public GameObject prefab;
public ParticleSystem particles;
public Bullet bullet;
}

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

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

public void FireAttack()
{
/// behaviour
Fire(bullets);
}

Public void IceAttack()
{
/// behaviour
Fire(bullets);
}

Public void WindAttack()
{
/// behaviour
Fire(bullets);
}

Перечисления могут сделать ваш код лучше …

public void WindAttack()
{
/// behaviour
Fire(bullets);
}

… Но для инспектора это плохо.
Лучше использовать отдельные переменные, так чтобы имена помогали увидеть, какое у них содержание. Используйте класс, чтобы сделать это изящно.


public class Bullets
{
public Bullet FireBullet;
public Bullet IceBullet;
public Bullet WindBullet;
}

Здесь предполагается, что нет других данных для огня, льда и воздуха.

37. Группируйте данные в сериализуемых классах, чтобы сделать параметры в инспекторе упорядоченнее. Некоторые объекты могут иметь десятки параметров. Это может стать кошмаром, при попытке найти правильную переменную в инспекторе. Чтобы упростить это дело, выполните следующие действия:

  • Определите отдельные классы для групп переменных. Сделайте их публичными и сериализуемыми.
  • В основном классе, определите публичные переменные каждого типа, как указанно ранее.
  • Не инициализируйте эти переменные в Awake или Start ; так как они сериализуемые, Unity позаботится об этом.
  • Вы можете указать значения по умолчанию, до присвоения значений в определении.

Это сгруппирует переменные в инспекторе в блоки, и облегчит управление ими.


public class MovementProperties //Not a MonoBehaviour!
{
public float movementSpeed;
public float turnSpeed = 1; //default provided
}

Public class HealthProperties //Not a MonoBehaviour!
{
public float maxHealth;
public float regenerationRate;
}

Public class Player: MonoBehaviour
{
public MovementProperties movementProeprties;
public HealthPorperties healthProeprties;
}

Текст

38. Если у вас много сюжетного текста, поместите его в файл. Не помещайте его в полях для редактирования в инспекторе. Сделайте, чтоб его легко было изменить, без редактора Unity, и особенно, без необходимости сохранения сцены.

39. Если вы планируете локализовать отдельно все строки в одном месте. Есть много способов сделать это. Один из способов заключается в определении класса Text , с публичным полем для каждой строки, и заданным значением по умолчанию на английском, например. Другой языковой подкласс, повторно инициализирует поля языковым эквивалентом.

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

Тестирование и отладка

42. Реализуйте свой собственный FPS-счетчика. Да. Никто не знает, что на самом деле измеряет FPS-счетчик Unity, но это не скорость кадров. Реализуйте собственный, так чтобы FPS соответствовал интуиции и визуальному контролю.

43. Реализуйте сочетаний клавиш, для снятия снимков экрана. Многие ошибки являются визуальными, и гораздо проще, сообщить о них, когда можно сделать скриншот. Идеальная система должна содержать счетчик в PlayerPrefs, чтобы последовательные скриншоты не перезаписывались. Скриншоты должны быть сохранены за пределами папки проекта, чтобы избежать случайного коммита в репозиторий.

44. Реализуйте сочетания клавиш, для печати позиции игрока в игровом мире. Это облегчает репорт о позиции ошибок, которые происходят в определенных местах в игровом мире, что в свою очередь облегчает отладку.

45. Реализуйте опции отладки для упрощения тестирования. Некоторые примеры:

  • Разблокировать все предметы (айтемы).
  • Отключить врагов.
  • Отключить GUI.
  • Сделать игрока непобедимым.
  • Отключить весь геймплей.

46. Для команд, которые достаточно малы, сделайте префаб с опциями отладки, для каждого члена команды. Положите идентификатор пользователя в файл, который не коммитится, и читается, когда игра запускается. И вот, почему:

  • Члены команды не закоммитят свои опции отладки по случайности, и никого не затронут.
  • Изменение опций отладки не изменит сцену.

47. Держите сцену со всеми элементами геймплея. Например, сцена со всеми врагами, все объекты, с которыми можно взаимодействовать, и т.д. Это делает легкой проверку функциональности, без необходимости играть слишком долго.

48. Определите константы для отладки сочетания клавиш, и держите их в одном месте. Клавиши отладки не нормально (не удобно) обрабатываются в едином месте, как и остальные части игрового ввода. Чтобы избежать конфликтов между сочетаниями клавиш, определите константы в одном месте. Альтернативой является, обрабатывать все клавиши в одном месте, независимо от того, является функция отладочной, или нет. (Недостатком является то, что этому классу могут понадобиться дополнительные ссылки на объекты).

Документация

49. Документируйте ваши настойки. Большинство документации должно быть в коде, но некоторые вещи должны быть задокументированы вне кода. Документация, повышает эффективность (если она актуальная).

Документируйте следующее:

  • Использование слоя (для коллизий, Culling, и Raycasting — по сути то, что должно быть на слое).
  • Использование тэгов.
  • Глубина GUI для слоев (что должно отображаться, поверх чего).
  • Настройка сцены.
  • Идиома предпочтений.
  • Структуры префабов
  • Слои анимации.

Стандарт именования и структура папок

50. Следуйте документированному соглашению об именовании и структурах папок. Следование ему облегчает поиск вещей, и понимание, что это за вещь.

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

Общие принципы именования.
  • Называйте вещи своими именами. Птица должна называться Bird .
  • Выбирайте имена, легко произносимые и запоминающиеся. Если вы делаете игру о Майя, не называйте свой уровень QuetzalcoatisReturn .
  • Будьте последовательными. Выбрав имя, придерживайтесь его.
  • Используйте стиль PascalCase, например: ComplicatedVerySpecificObject . Не используйте пробелы, подчеркивания или дефисы, с одним исключением (см. «Именования различных аспектов одного и того же»).
  • Не используйте номера версий, или слова для обозначения стадии прогресса (WIP, финал).
  • Не используйте аббревиатуры: DVamp@W должно быть DarkVampire@Walk .
  • Используйте терминологию из дизайн документации: если в документе анимация смерти называется Die, то надо использовать имя DarkVampire@Die , а не DarkVampire@Death .
  • Держите наиболее специфический дескриптор слева: DarkVampire , вместо VampireDark ; PauseButton , вместо ButtonPaused . Легче, например, найти кнопку паузы в инспекторе, когда не все кнопки, начинаются со слова «Button». [Многие люди предпочитают делать наоборот, потому что, это делает группировки, визуально более очевидными. Имена существуют не для группировок, для этого есть папки. Имена для различения объектов, одного и того же типа, и они должны помогать делать это быстро.]
  • Некоторые имена образуют последовательность. Используйте номера в этих названиях, например, PathNode0 , PathNode1 . Всегда начинайте с 0, а не 1.
  • Не используйте цифры для вещей, которые не образуют последовательность. Например, Bird0 , Bird1 , Bird2 , должно быть Flamingo , Eagle , Swallow .
  • Ставьте префикс временным объектам в виде двойного подчеркивания __Player_Backup .
Именования различных аспектов одного и того же

Используйте подчеркивание между основным именем, и тем, что описывает «Аспект». Например:

  • Состояние GUI-кнопок: EnterButton_Active, EnterButton_Inactive.
  • Текстуры: DarkVampire_Diffuse, DarkVampire_Normalmap.
  • Скайбоксы: JungleSky_Top, JungleSky_North.
  • LOD-группы: DarkVampire_LOD0, DarkVampire_LOD1.

Не используйте, это соглашение просто, для различия типов предметов, например, Rock_Small , Rock_Large , должно быть SmallRock , LargeRock .

Структура

Организация ваших сцен, папки проекта и папки скриптов, должны следовать аналогичной схеме.

Структура папок:

Materials
GUI
Effects
Meshes
Actors
DarkVampire
LightVampire
...
Structures
Buildings
...
Props
Plants
...
...
Plugins
Prefabs
Actors
Items
...
Resources
Actors
Items
...
Scenes
GUI
Levels
TestScenes
Scripts
Textures
GUI
Effects
...

Структура сцены:

Cameras
Dynamic Objects
Gameplay
Actors
Items
...
GUI
HUD
PauseMenu
...
Management
Lights
World
Ground
Props
Structure
...

Структура папки скриптов:

ThirdParty
...
MyGenericScripts
Debug
Extensions
Framework
Graphics
IO
Math
...
MyGameScripts
Debug
Gameplay
Actors
Items
...
Framework
Graphics
GUI
...

Как переопределить отрисовку инспектора.

1. Определите базовый класс для всех ваших редакторов:

BaseEditor : Editor
where T: MonoBehaviour
{
override public void OnInspectorGUI()
{
T data = (T) target;

GUIContent label = new GUIContent();
label.text = "Properties"; //

DrawDefaultInspectors(label, data);

If(GUI.changed)
{
EditorUtility.SetDirty(target);
}
}
}

2. Используйте рефлексию и рекурсию, чтобы составить компоненты:

public static void DrawDefaultInspectors(GUIContent label, T target)
where T: new()
{
EditorGUILayout.Separator();
Type type = typeof(T);
FieldInfo fields = type.GetFields();
EditorGUI.indentLevel++;

Foreach(FieldInfo field in fields)
{
if(field.IsPublic)
{
if(field.FieldType == typeof(int))
{
field.SetValue(target, EditorGUILayout.IntField(
MakeLabel(field), (int) field.GetValue(target)));
}
else if(field.FieldType == typeof(float))
{
field.SetValue(target, EditorGUILayout.FloatField(
MakeLabel(field), (float) field.GetValue(target)));
}

///etc. for other primitive types

Else if(field.FieldType.IsClass)
{
Type parmTypes = new Type{ field.FieldType};

String methodName = "DrawDefaultInspectors";

MethodInfo drawMethod =
typeof(CSEditorGUILayout).GetMethod(methodName);

If(drawMethod == null)
{
Debug.LogError("No method found: " + methodName);
}

Bool foldOut = true;

DrawMethod.MakeGenericMethod(parmTypes).Invoke(null,
new object
{
MakeLabel(field),
field.GetValue(target)
});
}
else
{
Debug.LogError(
"DrawDefaultInspectors does not support fields of type " +
field.FieldType);
}
}
}

EditorGUI.indentLevel--;
}

Описанный выше метод использует вспомогательный метод:

private static GUIContent MakeLabel(FieldInfo field)
{
GUIContent guiContent = new GUIContent();
guiContent.text = field.Name.SplitCamelCase();
object descriptions =
field.GetCustomAttributes(typeof(DescriptionAttribute), true);

If(descriptions.Length > 0)
{
//just use the first one.
guiContent.tooltip =
(descriptions as DescriptionAttribute).Description;
}

Return guiContent;
}

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

3. Определите новые пользовательские редакторы.

К сожалению, вы все равно должны определить класс, для каждого MonoBehaviour. К счастью, эти определения могут быть пустыми, вся фактическая работа делается в базовом классе.


public class MyClassEditor: BaseEditor
{}

Теоретически, этот шаг может быть автоматизирован, но я не пробовал этого делать.

Перевод Максим Саликов .

Этот продукт представлен в разных тарифных планах. Инди-разработчику для начала прекрасно подойдет бесплатная версия. Нажмите кнопку «Скачать сейчас» и загрузите версию для вашей ОС. Unity доступен для Mac OS и Windows, но обязательно убедитесь, что ваш компьютер соответствует системным требованиям.

Далее необходимо зарегистрироваться. Так вы сохраните историю загрузок из Unity Asset Store. Приложение запустится сразу после скачивания. В зависимости от ОС, установка может занять от двух до десяти минут. В процессе появится диалоговое окно, куда вам нужно будет ввести свои данные. Войдите в учетную запись, чтобы создать новый проект.

Выберите New Project и назовите его «My City». Никакие пакеты пока выбирать не нужно.

Внимательно выбирайте папку для ваших проектов, так как все файлы должны оставаться в одном месте. Для этого проекта оставьте директорию по умолчанию. Как только проект откроется, выберите File > New Scene и назовите сцену «MyFirstCity».

Интерфейс Unity

Возможно, интерфейс сначала покажется сложным, но мы по порядку разберем все его элементы. Перед вами должно появиться следующее окно:

Начнем снизу.

  • Вкладка Project содержит все файлы проекта: картинки, текстуры и префабы. С самого начала поддерживайте порядок в файлах, потому что по мере работы их количество будет стремительно расти, и рано или поздно вы рискуете запутаться.
  • Во вкладке Console отображается код или сообщения об ошибках.
  • В панели Hierarchy содержатся объекты текущей сцены. Любой проект начинается с элементов Light и Main Camera.
  • Вкладка Scene отображает текущую сцену с позиции основной камеры.
  • Вкладка Game отображает игру так, как ее увидит игрок.
  • Во вкладке Animator можно добавлять команды для контроллера анимации вашего персонажа.
  • Панель Inspector содержит такие настройки текущих объектов сцены, как цвет, текстура, скрипты и т. д.

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

  • Инструмент Hand позволяет свободно передвигаться по сцене.
  • Crossed Arrow используется для перемещения элементов сцены.
  • Rounded Arrows вращает элементы сцены.
  • Outward Arrows меняют размер элементов сцены.
  • Box позволяет увидеть сцену от первого лица.

На верхней панели также есть вкладки File, Edit, Assets, Game Objects, Component, Mobile Input, Window и Help . Со временем вы изучите все их подпункты и научитесь пользоваться ими.

Расположение элементов интерфейса


Впервые открыв Unity, вы увидите такое расположение элементов интерфейса, как на скриншоте выше. Чтобы изменить его, перейдите в Window > Layouts . Просмотрите каждый из предложенных вариантов, пока не найдете самый удобный для себя.

Вы можете также самостоятельно настроить расположение элементов, кликая левой кнопкой мыши по вкладкам и перетаскивая их, куда вам нужно. Я, например, работаю на двух мониторах, потому вкладка Game открыта у меня на одном, а Scene – на другом.

Загрузка ассетов

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

Перейдите в Window > Asset Store . Когда магазин откроется, вы увидите там множество объектов, текстур, персонажей и инструментов Unity. Конечно же, вы можете купить всё, что вам понравится, но в этом уроке я расскажу, как создавать текстуры самостоятельно, а также как пользоваться бесплатными ассетами. При первом открытии магазина вас могут попросить войти в вашу учетную запись.

Введите в строку поиска по магазину “Yughues Free Concrete Materials ”. Вам откроется следующее окно:

Нажмите Download , дождитесь окончания загрузки и кликните Import . В зависимости от вашей ОС процесс может занять от двух до десяти минут. По завершении импорта новый ассет появится во вкладке Project .

Подобным образом загрузите и импортируйте из магазина City Props Pack .

Нам также потребуется скайбокс – найдите и импортируйте Wispy Skybox .

Теперь пришло время добавить пакеты Unity. Выберите Assets > Import Package . Нам потребуются пакеты Characters, Cameras и Environment .

Поиск бесплатных ассетов

Чтобы найти текстуру дороги, я ввела “road textures ” в поисковике Bing и перешла во вкладку «Изображения». Следует убедиться, что поиск выполняется по файлам с бесплатной лицензией.

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

Теперь аналогичным образом подыщем текстуры для зданий. Я использовала запрос “building textures”. Не забывайте поддерживать порядок в файлах и сохранять изображения в соответствующую папку Unity.

Примечание: работая в Unity над коммерческим проектом, позаботьтесь о лицензии ваших ассетов. Изображения, не требующие лицензионных отчислений, можно купить на Envato Market.

Создайте папку во вкладке Project и назовите ее Artwork . Перейдите в Asset > Import Asset и выберите изображение, затем переместите его в папку Artwork.

Примечание: при перемещении изображения сразу после сохранения проекта оно может не отобразиться или отобразиться без текстуры.

Как только все ассеты загрузятся, можно будет приступать к созданию города. Но перед этим сохранитесь: File > Save Scene.

Ландшафт

Выберите GameObject > 3D Object > Terrain , чтобы добавить в сцену ландшафт.

Примечание: При выбранном инструменте Hand можно приближать и отдалять камеру по отношению к объектам с помощью колесика мыши.

Результат должен выглядеть, как на картинке выше. Возможно, при первом открытии Unity 5 у вас появится пара сообщений о нарушении работы шейдера. Если ваш проект выглядит, как на скриншоте ниже, – не волнуйтесь, это легко исправить. Выберите Terrain , затем кликните по значку шестеренки сразу под Inspector , пролистайте вниз до пункта Material и выберите опцию Built-In Legacy Diffuse . Это должно помочь.

Положение камеры

Когда вы выбираете объект в панели Hierarchy , информация о нем появляется в окне Inspector . Здесь вы можете настраивать объект, добавлять текстуры, коллайдеры и код.

Выставим правильное положение для камеры. Выберите Main Camera в Hierarchy . Теперь перейдите ко вкладке Inspector и в блоке Transform введите следующие значения для Position : 265, 20, 20.

Текстура для ландшафта

Выберите Terrain в Hierarchy и кликните по иконке кисточки в окне Inspector. Далее нажмите левой кнопкой мыши Edit Textures под блоком Textures , а затем – Add a Texture . Откроется небольшое окно, в котором нужно будет выбрать текстуру. По завершении появятся текстуры, которые вы импортировали из Asset Store. Выберите двойным кликом ту, которая вам нравится. Я остановилась на Dark Concrete .

Скайбокс

Unity поставляется с довольно неплохим стандартным скайбоксом, но мне больше нравится тот, который мы загрузили ранее. Выберите Main Camera, затем перейдите в Inspector и нажмите Add Component внизу окна. Введите Skybox, нажмите на круглую иконку справа и выберите в появившемся окне нужный скайбокс. Теперь, открыв вкладку Game, вы увидите там добавленный скайбокс.

Формы зданий

Чтобы добавить форму для здания, выберите Game Object > 3D Object > Cube . Сначала вы не увидите этот куб, потому что он будет далеко. Переместите его на обозримую область, выбрав Cube в окне Hierarchy и задав ему следующее расположение: 300, 25, 100. Выставьте его размер на 20, 50, 20. Размер можно менять как специальным инструментом на панели слева вверху, так и меняя значения в соответствующих полях. Добавив куб, кликните по нему правой кнопкой мыши в Hierarchy и переименуйте на Building 1.

Отлично, теперь добавим еще несколько зданий. Повторите действия выше. В окне Hierarchy появится еще один куб под названием Cube (1), переименуйте его на Building 2. Задайте ему размер 20, 70, 20 и положение 275, 25, 100.

Добавляя здания, меняйте их размер и положение. Убедитесь, чтобы они выстроены по одной линии, для этого среднее значение должно оставаться на 25. Как и размер, положение объектов можно менять не только методом ввода значений, но и инструментом перемещения. Повторяйте все действия, пока у вас не получится пять зданий, от Building 1 до Building 5. Я расположила здания через 25 единиц друг от друга: 250, 0, 100, 225, 0, 100 и т. д. Не забудьте сохранить сцену.

Примечание: вы также можете кликнуть правой кнопкой мыши по зданию в окне Hierarchy, чтобы скопировать и вставить его.

Текстуры зданий

Пора превратить эти неприглядные фигуры в здания. Кликните по папке Artwork во вкладке Project (куда вы загрузили текстуры зданий), выберите текстуру и перетащите ее в окно Scene. Вы увидите изменения в окнах Scene и Game . Меняйте настройки, двигайте и вращайте здания до тех пор, пока не получите нужный результат.

Примечание: если текстура стоит задом наперед, поверните ее по оси Z на 180?.

Дорога

Чтобы добавить дорогу, выберите Game Object > 3D Object > Plane и задайте ей следующее положение: 250, 0.2, 80. Поверните ее по оси Y 90? и измените размер на 1, 1, 15. Теперь выберите текстуру дороги и добавьте ее на созданную плоскость, переименовав последнюю в Road .

Строим улицу

Готовые проекты Unity содержат, как правило, тысячи объектов, скриптов и префабов, потому очень важно поддерживать порядок в файлах. Сейчас мы немного упорядочим содержимое окна Hierarchy.

Любой город обычно делится на кварталы и улицы, и наш не станет исключением. Выберите Game Object > Create Empty, и в Hierarchy появится новый элемент под названием GameObject. Переименуйте его в Block1(L), затем выделите все ваши здания и переместите под этот объект, сделав их дочерними по отношению к нему.

Теперь можете поменять текстуры у зданий на другой улице или при желании загрузить новые. Для изменения текстуры следует выбирать каждое здание по отдельности, иначе вы сразу поменяете текстуру для всех зданий в ряду. Измените положение камеры на 340, 10, 80 и поверните ее на -80?. Не забудьте сохраниться.

Примечание: если вам не нравится положение какого-либо элемента, поменяйте его на свое усмотрение.

City Props Pack

Начиная с этого шага я буду использовать инструменты панели переключения в верхнем левом углу.

Откройте вкладку Project и разверните папку City Props Pack . Пролистайте вниз до папки Prefabs, откройте ее и найдите элемент под названием Stop sign . Выберите его, и он появится в окне Inspector.

Подвиньте камеру ближе к первому зданию, выберите знак и перетащите его в окно сцены. При необходимости поменяйте его размер. Я использовала следующие настройки: 0.2, 0.2, 0.2.

Добавим еще какие-нибудь детали. Выбирайте все элементы, какие вам нравятся, и располагайте их вдоль улицы. Любой объект можно скопировать и вставить несколько раз в окне Hierarchy. Чтобы не нарушать порядок в файлах, создайте пустой родительский элемент под названием City Props и переместите туда все соответствующие элементы. Сохраните сцену.

Примечание: Если объекты в сцене светятся белым, поменяйте настройки шейдера на Legacy Shaders / Bumped Diffuse .

Деревья

Unity поставляется со стандартным пакетом деревьев, но вы всегда можете загрузить дополнительные ассеты из магазина.

Кликните по Terrain в Hierarchy . Затем нажмите на иконку дерева в блоке Terrain окна Inspector. Под настройками выставьте значение Brush Size на 1 и после этого нажмите Edit Trees > Add Tree . В блоке Tree Prefab кликните по круглой иконке справа.

Выберите дерево (я остановилась на Broadleaf ) и добавьте его двойным кликом. Теперь оно отобразится под блоком Trees в окне Inspector . Используйте мышь, чтобы расположить дерево в сцене. Синий индикатор рядом с курсором укажет место, куда оно будет добавлено. Так как значение Brush size у нас 1, вы будете добавлять по одному дереву за раз. Менять размер деревьев можно с помощью опции Tree Height . Если вас не устроит полученный результат, вы всегда можете нажать Edit Trees и удалить дерево.

Персонаж от третьего лица

Пришло время создать первого обитателя нашего виртуального города. Разверните папку Standard Assets во вкладке Project и нажмите Characters > ThirdPersonCharacter . Пролистайте до папки Prefabs и перетащите объект под названием ThirdPersonController в вашу сцену. Задайте контроллеру положение 315, 0.1, 78 и размер 3, 3, 3.

Его также можно развернуть в любом нужном вам направлении. Нажмите Play и попробуйте с помощью клавиатуры управлять действиями персонажа.

Нам нужно, чтобы камера следовала за персонажем, иначе он будет пропадать из поля зрения. Выберите элемент Main Camera в Hierarchy и перетащите его под ThirdPersonController так, чтобы камера стала дочерним элементом. Теперь, когда вы нажмете Play, камера будет следовать за персонажем.

Контроллер от первого лица

Можно также добавить возможность просмотра от первого лица. Для этого перейдите во вкладку Project и выберите Standard Assets > Prefab > FPS Controller . Перетащите контроллер в сцену, поверните его и настройте размер. Обратите внимание, что FPS Controller имеет собственную камеру, потому для его использования нужно будет удалить MainCamera.

Примечание: если ваш персонаж проваливается сквозь землю, скорее всего, вы расположили его слишком низко. Кликните дважды по персонажу в окне Hierarchy, и он отобразится в окне Scene. Поднимите контроллер выше вручную или впишите напротив Y значение 1.

Поздравляю! Вы только что создали свой первый трехмерный город Unity 5! Как видите, это легко и увлекательно. Вы можете проявить фантазию и добавить туда всё, что заходите: машины, магазины, дома и т. д.

Для начала давайте познакомимся с Unity3D. Когда Вы запустите Unity3D в первый раз, всплывет окно Project Wizard . Вы можете импортировать один из встроенных пакетов Unity. Пакеты - это коллекции различных файлов (кода, моделей, аудио-файлов, текстур и т.д.), которые хранятся в виде иерархической структуры, инкапсулированной в файлы с расширением .unitypackage . Пакеты могут быть экспортированы из любого Unity-проекта. Таким образом можно очень просто переносить различные файлы между проектами, сохраняя их иерархию. Сейчас нам не нужно импортировать какие-либо пакеты.

Окно Unity Project Wizard

После того, как вы зададите путь для нового проекта, нажмите кнопку Create , чтобы завершить создание проекта. Если Вы открыли Unity и создали проект заблаговременно, вы всегда можете создать новый проект, нажав File New Project , чтобы вызвать окно Project Wizard .

Создание нового проекта Unity

Интерфейс Unity разделен на несколько вкладок:

  • Вкладка Project содержит все ресурсы, используемые в игре. Для опрятности рекомендуется, чтобы все файлы проекта находились в папках с соответствующими именами (Materials, Textures, Models, Prefabs и т.д.). Это окно показывает, как файлы хранятся на вашем жестком диске, но очень важно, чтобы любые изменения файлов проекта были сделаны из вкладки Project, а не из Проводника, иначе Вы рискуете необратимо потерять связь между файлами.
  • Вкладка Console отображает полезные отладочные сообщения. Если у вас есть минимальный опыт в программировании, вы, вероятно, знаете, почему именно они полезны.
  • Вкладка Inspector показывает различные компоненты, содержащиеся в объектах из вкладок Hierarchy или Project . Вы можете модифицировать любые значения редактируемых объектов отсюда.
  • Вкладка Hierarchy содержит список названий всех объектов, расположенных на текущей сцене.
  • Вкладка Scene показывает игровой мир с произвольной точки (отличной от точки, в которой расположена главная игровая камера). Вы можете изменить позицию этой камеры с помощью клавиш W, S ,A, D и правой кнопки мыши.
  • Вкладка Game показывает, что происходит, когда вы начинаете игру, с точки зрения игровой камеры. В отличие от вкладки Game , вкладка Scene отображает сетку.

Вы можете расположить вкладки, как вам удобно, перетащив их мышкой в нужное место.

Интерфейс Unity

Любой объект или скрипт, добавленный в проект, может быть сохранен в файле сцены с расширением .unity . Сцены идентичны игровым уровням. Unity-разработчик может разместить игровые файлы на отдельную сцену, когда это необходимо, и загрузить их во время выполения кода. Любой проект может содержать несколько сцен. Чтобы сохранить текущую сцену, нажмите File → Save Scene / Save Scene as… и наберите название в окне проводника.

Сохранение сцены

Сохраните ее в папке Assets - корневой папке Unity-проекта.

Именование сцены

Если вы откроете папку Assets во вкладке Project , вы можете обнаружить там только что созданную сцену. Кликните здесь правой клавишей мыши и создайте три новых папки: Code, Materials и Textures , как показано на картинке:

Создание новой папки

Необходимые папки

Теперь мы готовы начать! Перетащите текстуры куба и скайбокса в папку Textures .

Импортированные в проект текстуры куба и скайбокса

Затем зайдите в папку Materials и создайте четыре материала:

  • SkyboxMaterial,
  • BottomMaterial,
  • SideMaterial,
  • TopMaterial.

Материалы добавляют цвета на 3D-объекты с помощью программ, называемых шейдерами и обрабатываемых на GPU. Больше информации о материалах Unity и шейдерах вы можете получить . Три материала, которые мы создали, будут применены к сторонам куба, который мы создадим в следующем разделе.

Создание нового материала

Материалы для скайбокса и сторон куба

Кликните левой кнопкой мыши на BottomMaterial . Во вкладке Inspector кликните по кнопке Select , расположенной в компоненте Texture материала, а затем, во всплывшем окне, выберите текстуру bottom .

Обззор материала во вкладке Inspector

Выбор компонента текстуры

Затем выберите соответствующие текстуры для SideMaterial и TopMaterial , как показано на картинке ниже.

Материалы куба с загруженными текстурами

Если вы хотите, чтобы на заднем плане отображался красивый пейзаж, вы можете добавить скайбокс. Для этих целей мы создали SkyboxMaterial , на который мы наложим шесть оставшихся текстур из папки Textures .

Нажмите левой кнопкой мыши на SkyboxMaterial . Во вкладке Inspector , рядом с меткой Shader, кликните на выпадающий список и выберите RenderFX → Skybox . Это встроенные в Unity шейдеры, которые имплементируют базовые (модель освещения Блинна-Фонга, рельефное текстурирование, отражения, прозрачность и т.д.) и несколько продвинутых шейдеров, таких как параллакс-эффект. Вы также можете писать свои шейдеры и добавлять их в проект.

Выбор шейдера для отрисовки скайбокса

Выбор подходящих текстур скайбокса

Далее, мы должны добавить скайбокс на нашу сцену. Перейдите в Edit → Render Settings . Во вкладке Inspector, рядом с меткой Skybox Material, нажмите на маленький кружок справа и выберите SkyboxMaterial из материалов проекта.

Выбор материала скайбокса в RenderSettings

Если мы приглядимся, мы можем обнаружить грани skybox-куба. Этого можно избежать с помощью наложения текстур. Когда текстура наложена на другую, пиксели, расположенные на краях текстуры, повторяются, заполняясь цветом краев модели, на которой они расположены. Больше информации о наложении текстур можно получить .

Типичное поведение неналоженных текстур

Перейдите в папку Textures во вкладке Project , выберите все изображения, в пункте Wrap Mode выберите Clamp из выпадающего списка и нажмите Apply .

Установка Wrap Mode для всех текстур проекта

Создаем куб

Было бы очень заманчиво использовать встроенный примитив Unity - куб - как основу для кубов Minecraft, и расположить соответствующие текстуры из текстурного атласа на стороны куба, используя UV-преобразования , но в этом руководстве мы будем придерживаться простых методик (с наименьшим количеством внешних ресурсов) и будем использовать отдельные меши для каждой стороны.

В верхнем левом меню кликните на GameObject → Create Other → Quad. Повторите это действие еще пять раз (нам нужно создать шесть сторон куба).

Создание граней куба

Теперь назовите каждую из шести сторон соответствующим именем:

Top , Bottom , Right , Left , Front , Back .

Объекты, расположенные на сцене, называются GameObject . Чтобы переименовать GameObject , кликните правой клавишей мыши на нем во вкладке Hierarchy и нажмите Rename .

Переименование граней куба

Если вы только начинаете знакомиться с Unity, вам крайне рекомендуется ознакомиться с навигацией в окне Scene и позиционированием GameObject , прежде чем идти дальше.

После создания игровые объекты будут размещены на сцене случайным образом (на самом деле, новые GameObject расположены в точке текущего расположения камеры). Мы должны расположить все стороны куба. Чтобы выровнять их, во вкладке Hierarchy кликните на каждую сторону и модифицируйте её позицию и вращение во вкладке Inspector таким образом:

Преобразование значений для каждой грани

Вуаля! Наш серый куб готов:

Обычный серый куб

Если куб не центрирован в окне Scene, дважды кликните на одной из его сторон во вкладке Hierarchy , чтобы выровнять камеру.

Во вкладке Project зайдите в папку Materials. Чтобы создать красивый пиксельный куб, мы должны переместить следующие материалы:

Куб с текстурами

Замечательно! Выглядит, как куб из Minecraft, но сейчас у нас есть шесть разделенных частей, а не автономный GameObject , который мы могли бы разместить на нашей сцене. Мы будем использовать простую систему иерархий Unity, чтобы переместить эти части в один GameObject . Она позволяет любому GameObject стать потомком другого GameObject на сцене с помощью простого перетаскивания объекта-потомка на желаемый объект-родитель. Это чрезвычайно удобно, потому что Transform потомка (позиция, вращение и масштаб объекта) станет относительным родительскому объекту.

В левом верхнем меню выберите Game Object → Create Empty . Это действие создаст пустой GameObject , который будет содержать только компонент Transform .

GameObject размещён в центре сцены

Теперь выберите шесть сторон куба и перетащите их в новый пустой GameObject .

Сборка куба

Если вы обнаружили ошибки, как на картинке ниже, учтите, что это обычное явление, когда вы вручную меняете иерархию GameObject . Просто нажмите Clear on Play во вкладке Console , чтобы очистить лог ошибок, когда запускаете игру.

В версии Ubuntu 11.04, произошло серьезное изменение в графической среде пользователя, теперь вместо GNOME в его традиционном виде все "крутится" под Unity. Так, что теперь Ubuntu еще больше похожа на Mac OS X.

Пустой рабочий стол Unity:

Верхнее меню Unity, так называемый Dash. По сути это текстовый поиск по именам программ и файлов. Вы пишете буквы, а оболочка выводит программы и файлы в которых есть такие буквы :

Кроме этого, в меню Dash есть Линзы (Dash Lens). Это переключатели для поиска только в определенных категориях и местах. Можно пролистать все установленные программы если воспользоваться линзой "Программы" :

Существует набор линз для разных предметных областей. Например есть линза "Википедия":

По умолчанию, "из коробки" устанавливаются линзы "Home", "Программы", "Файлы", "Музыка" и "Видео". Дополнительные линзы можно установить через репозиторий Ubuntu или сторонние репозитории.

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

Важное примечание

Относительно Unity нужно знать несколько вещей:

  • Для работы Unity необходимо установить драйвера на видеокарту, которые поддерживают OpenGL, а также движок визуальных эффектов Compiz. В Ubuntu 11.04 Compiz устанавливается автоматически, а подходящий драйвер может не установиться автоматически и в этом случае Ubuntu 11.04 будет загружаться с обычным рабочим столом GNOME.
  • В Ubuntu 11.04 вы можете отказаться от использования Unity и работать в GNOME привычного вида. Для этого нужно всего лишь завершить сеанс пользователя и заново войти в систему выбрав на логин-экране опцию "Ubuntu Классический". Эта опция доступна внизу логин-экрана после ввода имени пользователя (но ее нужно выбрать до ввода пароля!).
  • Если ваша видеокарта не поддерживает OpenGL, можно установить пакет Unity-2d, который рабтает как надстройка над GNOME.

Актуализация 2013

В версии 12.04 П акет Unity-2d устанавливается "из коробки". Для загрузки в облегченном варианте нужно просто выбрать Unity-2d в экране авторизации (до ввода пароля).

Кнопка Dash перемещена из верхней панели в левую боковую панель быстрого запуска (Launcher). Но физически она осталась почти на том же месте - вверху слева.

Организация интерфейса в Unity

Вверху экрана размещается панель которая содержит (слева направо ) кнопку открытия меню Dash, пространство для меню программ и системный трей.

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

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

Два этих решения - интеграция меню программ в системную панель и перевод панели задач на левую границу экрана дают больше рабочего пространства по вертикали. Вот снимок экрана, на котором во весь экран раскрыт Наутилус:

Меню Наутилуса размещено в верхней панели Unity. Слева панель быстрого запуска (Launcher) с кнопками для запуска часто используемых программ. По вертикали под Наутилус используется почти все пространство монитора, за исключением 24 пикселей на верхнюю панель Unity.

Есть еще одно изменение интерфейса Unity по сравнению с традиционным, это отсутствие скроллбаров как видимой части окна программы. В Unity скроллбары вынесены за границы окна и активизируются (становятся видимы) только при наведении курсора мыши на границу окна.

Как пользоваться Unity

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

Как вставить кнопку запуска программы в панель быстрого запуска (Launcher) ?

Как удалить кнопку запуска программы из панели запуска?


Настройка Unity

Для того, чтобы изменить настройки Unity нужно установить пакет compizconfig-settings-manager, который по умолчанию не устанавливается. После его установки в Dash можно ввести "ccsm" и появится программа "Менеджер настроек CompizConfig".
В окне программы нужно открыть раздел "Рабочий стол" и там будет виден "Unity".

Актуализация 2013

Теперь есть еще одна программа для настройки интерфейса Unity -MyUnity , пакет для установки так и называется - myunity:

Использование клавиатуры в Unity

Unity еще более, чем классический GNOME, унифицирован с Windows по клавиатурным комбинациям. Теперь нажатие обеих (и правой и левой) клавиш Win дает одинаковый результат.

  • F10 - активизировать трей. Затем можно перемещаться по элементам трея стрелками.
  • Win - открыть меню программ (Dash) с поиском. По мере того как вы вводите буквы в поле, программа выдает вам подходящие варианты. Поиск работает как по английскому языку (оригинальному имени программ) так по русскому - именам ярлыков программ.
  • Alt+Tab - переход между окнами запущенных программ.
  • Win+D - свернуть все окна и освободить рабочий стол. В Ubuntu 11.10 сделали Ctrl+Alt+D.
  • Win+R - диалог "Выполнить", ранее открываемый по Alt+F2. В нем можно вписать однострочную терминальную команду. Есть поиск по истории введенных команд. В Ubuntu 11.10 снова сделали Alt+F2 .
  • Tab или стрелки вверх\вниз\вправо\влево - перемещение в меню.
  • Win+S - показать 4 рабочих стола сразу.
  • Win+Tab - при нажатии этого сочетания на каждой кнопке появляется номер, нажав этот номер на клавиатуре можно запустить\перейти в эту программу. Нужно удерживать нажатой Win до ввода цифры.
  • Ctrl+L - изменить режим адресной строки в Наутилусе с "табов" на текстовый.

Переопределить сочетания клавиш можно через апплет "Клавиатура" и через CompizConfig:

Тюнинг рабочего стола

Во-первых можно использовать "Менеджер настроек CompizConfig" для настроек различных визуальных эффектов.

Во-вторых можно установить дополнительные пакеты, которые реализуют какие-либо функции управления или удобства. Например пакет Glx-Dock (также известный как Cairo-Dock) реализует Dock панель в стиле Mac OS X и эту панель можно использовать для размещения кнопок запуска программ, которые не вмещаются на панели Unity. Выглядит это примерно так:

Для любителей глубоко копнуть

Если ваша программа не отображается в трее, хотя и должна можно попробовать вот такие команды:

gsettings set com.canonical.Unity.Panel systray-whitelist "["all"]"
gsettings set com.canonical.Unity.Panel systray-whitelist "[""]"
gsettings set com.canonical.Unity.Panel systray-whitelist "["имя_вашей_программы"]"

Если вы хотите изменить контекстные меню кнопок из панели запуска то сделать это можно скопировав файл нужной кнопки из папки /usr/share/applications в папку ~/.local/share/applications. Эти файлы имеют расширение.desktop. например nautilus-home.desktop.

Например так:


Name=Изображения
Exec=nautilus Изображения
TargetEnvironment=Unity


Name=Загрузки
Exec=nautilus Загрузки
TargetEnvironment=Unity

Можно еще глубже копнуть:

Или на телефон +7 918-16-26-331 .

Даже небольшая сумма может помочь написанию новых статей:)




© 2024, lenkom35.ru - Бесплатные юридические консультации