Это третья и заключительная часть нашего урока о новом GUI в Unity. Для тех, кто пропустил предыдущие уроки, кратко опишем, что в них было, чтобы вы могли решать - читать их или пропустить.
В учебнике по новому GUI в Unity. Часть 1 Вы создали сцену с меню с адаптивным фоном и четко контролируемыми графическими элементами, благодаря мастерскому использованию якорей, точки отсчета и других крутых трюков.
В учебнике по новому GUI в Unity. Часть 2 мы поговорили об анимации кнопок и сделали нашу игру супер-интерактивной. Теперь мы займемся усовершенствованием этих навыков, чтобы дать вам более полное понимание нового графического интерфейса Unity. Но красивая новая менюшка – это только начало! Попробуем-ка перенести сцену из игры RocketMouse со старого GUI на новый.
Начало работы
Чтобы начать, просто откройте сохраненный во 2й части урока проект Unity (или загрузите его по ссылке, распакуйте и откройте в Unity.
Создание раскрывающегося меню
Иногда бывает нужно предоставить пользователям легкий доступ к некоторым настройкам игры, но при этом не загромождать экран. Начнем работу с раздвижным меню. Вы уже видели это раньше, эта штука представляет собой маленькую невзрачную кнопочку, которая постоянно маячит на виду, и меню с набором опций, выезжающее из-за края экрана.
Для начала добавим кнопку для открытия этого меню. Вы уже знаете как добавить кнопку (если вы изучали первых две части этого урока). Если же нет, то выберите GameObject\UI\Button
в меню. Переименуйте добавленную кнопку в btn_slide
и удалить вложенный объект Text
, поскольку нам не понадобится надпись на кнопке. Выберите btn_slide
в Иерархии и откройте папку Menu
в Браузере проекта. Перетащите изображение btn_9slice_normal
в поле Source Image
в Инспекторе. Теперь установите положение и размер кнопки следующим образом:
- Якоря
Anchors
установите в bottom-left
.
-
Pos X
и Pos Y
сделайте равными 80
.
Width
(Ширина) и Height
(Высота) пусть будут равны 64
.
Итак, первый шажок уже сделан, давайте теперь добавим маскирующую панель.
Для этого нам потребуются две панели. Одна будет определять маску, а другая будет двигаться в пределах этой маски. Выберите GameObject\UI\Panel
чтобы создать первую панель, которая будет маской. При этом Panel
появится в Иерархию. Выделите ее и выполните следующие действия:
- Переименуйте
Panel
в pnl_mask
.
- Перетащите
pnl_mask
на btn_slide
, чтобы добавить его в качестве дочернего объекта.
- Установите Якоря
Anchors
в top-center
(верх-середина).
- Установите
Pivot
в (0.5, 0)
Pos X
и Pos Y
пусть будут равны 0
.
- Зададим размеры:
Width
будет равно 64
, а Height
- 192
.
- Добавьте компонент маски, нажав на кнопку
Add Component
и выбрав UI\Mask
.
- Снимите галочку
Show Mask Graphic
внутри окна компонента маски.
Вам не всегда придется добавлять панель с маской как дочерний узел кнопки. Но если уж вы решили так и сделать, убедитесь, что при движении кнопки панель маски двигается вместе с ней.
Теперь добавим содержимое панели. Добавьте другую панель, выбрав GameObject\UI\Panel
и выполните следующие действия:
- Переименуйте ее в
pnl_content
- Добавить его как ребенка
pnl_mask
Вы заметили, что вы можете увидеть только небольшую часть белой панели, хотя ее размер не изменится? После добавления ее как "потомка" к панели с маской, то вы увидите только ту часть pnl_content, которая находится внутри прямоугольника pnl_mask.
- Установите Якоря
Anchors
в положение stretch-stretch
(тянется-тянется).
- Для
Left
, Top
, Right
и Bottom
задайте значения, равные 0
.
Pivot
пусть будет (0.5, 1)
Теперь пришло время изменить фоновое изображение для панели с содержимым. Откройте папку Menu
в Браузере проекта и выберите изображение slide_menu_panel_9slice
. Откройте Sprite Editor
(Редактор спрайтов) в Инспекторе и установите всем рамкам Border
значения, равные 8
. Нажмите на Apply
(Применить).
Теперь, выберите pnl_content
в Иерархии, а затем перетащите slide_menu_panel_9slice
из Браузера проекта в поле Source Image
в Инспекторе. На представленном ниже анимированом изображении вы можете увидеть как должна выглядеть панель с содержание и как работает маска: вот панель есть..., а вот ее нет!
Как вы видите, маска работает аналогично окну в стене. Если кто-то идет за стеной, вы можете увидеть его только тогда, когда он проходит мимо окна. Теперь добавим три кнопки для раскрывающегося меню. Для создания первой кнопки выберите GameObject\UI\Button
, переименуйте в btn_about
и удалите потомок text
. Перетащите кнопку btn_about
в Иерархию, вложив ее в pnl_content
. Откройте папку Menu
в Браузере проекта и перетащите slide_menu_btn_about
в Source Image
в Инспекторе, а потом нажмите на Set Native Size
. Установите Якоря Anchors
в top-center
, Pivot
- (0.5, 1)
. После задайте Pos X
и Pos Y
значения, равные 0
. Остальные две кнопки попробуйте добавить сами по-аналогии. Назовите их btn_achievements
и btn_leaderboards
и воспользуйтесь изображениями slide_menu_btn_achievements
и slide_menu_btn_leaderboards
соответственно. Если у вас что-то не получилось, то читайте описание ниже.
Правой кнопкой мыши кликните на btn_about
в Иерархии и выберите Duplicate
(Сделать копию).
Переименуйте копию btn_about
в btn_achievements
и измените Pos Y
на -64
, а затем используйте slide_menu_btn_achievements
из папки Menu
в Браузере проекта в качестве источника изображения..
После этого, дублируйте кнопку Достижение (btn_achievements
). Назовите копию btn_leaderboards
, установите Pos Y
в -128
и используйте slide_menu_btn_leaderboards
в качестве источника изображения. Вот, что у вас должно получиться:
Создание панели прокрутки вверх и вниз
Для того, чтобы панель скользила вверх и вниз вы будете использовать ту же технику, что вы уже применили на кнопках и диалоге настроек. Это будет нелегко). Выполните следующие действия:
- Выберите
pnl_content
в Иерархии и откройте вкладку Animation
(Анимация).
- Создайте новый клип, используя опцию
[Create New Clip]
.
- Назовите анимацию
sliding_menu_down
и сохраните ее в папку Animations.
Кликните
на отметке 1:00
на линейке времени
. Это также должно добавить возможность записи в режиме Animation. Когда вы нажмете на красную круглую кнопку, кнопки воспроизведения тоже должны стать красными.
- Установите
Top
на 192
в Инспекторе и остановите запись.
- Откройте папку
Animations
в Браузере проекта, выберите sliding_menu_down
и в Инспекторе снимите галку напротив Loop Time
.
- Выберите в Иерархии
pnl_content
и откройте вкладку Animator
(Аниматор). Скопируйте и вставьте состояние sliding_menu_down
чтобы создать дубликат.
- Переименуйте копию в
sliding_menu_up
и установите ее Speed
(Скорость) в -1
в Инспекторе.
- Во вкладке Аниматор,
set sliding_menu_up as default
by right-clicking
on it and selecting Set As Default
.
- Создайте два перехода: от
sliding_menu_up
к sliding_menu_down
и от sliding_menu_down
к sliding_menu_up
.
- Добавьте новый булевский параметр по имени
isHidden
и задав ему дефолтное значение равное true
.
- Выберите переход от
sliding_menu_up
к sliding_menu_down
и в списке условий установите isHidden
to true
.
- Выберите переход от
sliding_menu_down
к sliding_menu_up
и на этот раз установите условие isHidden
равно false
.
- В завершении выберите
pnl_content
в Иерархии и отключите компонент Animator
как вы это делали для диалога настройки. Это необходимо, поскольку вы не хотите, чтобы анимация начиналась при старте.
Добавление кода для выезжающего меню
Откройте MonoDevelop еще раз. И нечего брюзжать, все-таки создание пользовательского интерфейса с помощью GUI предыдущей версии в MonoDevelop заняло бы у вас намного больше времени. Свой смысл в этом есть, так что откройте UIManagerScript
в MonoDevelop и добавьте следующую переменную:
public Animator contentPanel;
После этого добавьте следующий метод:
public void ToggleMenu()
{
contentPanel.enabled = true;
bool isHidden = contentPanel.GetBool("isHidden");
contentPanel.SetBool("isHidden", !isHidden);
}
Здесь мы включаем компонент аниматора при открытии скользящего меню и устанавливаем правильное значение параметра isHidden
.Последний штрих - нужно с самого начала переместить панель вниз, поэтому добавьте Start()
:
void Start()
{
RectTransform transform = contentPanel.gameObject.transform as RectTransform;
Vector2 position = transform.anchoredPosition;
position.y -= transform.rect.height;
transform.anchoredPosition = position;
}
В методе Start
Вы просто берете высоту панели с контентом и перемещать ее вниз на это значение, что делает панель полностью скрытой.
Вы могли бы передвинуть панель вниз в Unity и вообще не писать этот код, используя метод Start
. Но это усложнило бы работу с содержимым панели в Unity, так как компонент маски спрятал бы ее.
Сохраните скрипт и переключитесь обратно в Unity. В Unity выберите UIManager
в Иерархии и перетащите pnl_content
из Иерархии на поле Content Panel
в Инспекторе.
Теперь выберите btn_slide
в Иерархии. В Инспекторе найдите список обработчиков событий On Click (Button)
и добавьте новый, кликнув на кнопку +
. После этого перетащите UIManager
из Иерархии к новому обработчику. Затем, в выпадающем меню функций выберите UIManagerScript\ToggleMenu ()
.
А теперь запустите сцену и поиграйтесь открывая и закрывая наше меню.
Добавление иконки с вращающейся шестеренкой
А не кажется ли вам, друзья мои, что чего-то не хватает? Именно! Значка вращающейся шестеренки на самой кнопке. Раз так, за дело! Для начала добавить изображение в качестве дочернего объекта в btn_slide, и анимировать его при открытии и закрытия меню.
Выберите GameObject\UI\Image
для создания нового изображения. Перетащите его на btn_slide
в Иерархии, чтобы добавить в качестве дочернего объекта. После этого, выполните следующие действия:
- Переименуйте изображение в
img_gear
- Установите Якоря в
middle-center
Pos X
и Pos Y
должны быть установлены в нуль.
- Откройте папку
Menu
в браузере проекта и перетащите изображение slide_menu_gear
в папку Source Image
в Инспекторе.
- Нажмите на
Set Native Size
.
К этому моменту вы уже должны уметь создавать два состояния анимации и параметр переключения между ними с закрытыми глазами. В данном случае вам нужно создать шестеренку, вращающуюся влево, и изменить анимацию так, чтобы шестеренка вращалась вправо. Помните следующее:
Длительность анимации
должна быть идентичной длительности анимации выезжающей панели. Это не проблема, так как продолжительность всех анимаций в этом уроке равна 1 секунде.
- Шестеренка должна вращаться на 360 градусов вокруг оси Z (Вращение Z).
- Используйте то же имя
isHidden
в качестве названия параметра и установите его дефолтное значение на true
.
- Не забудьте отключить зацикливание и компонент аниматор.
Если вам чего-то непонятно, то прочтите инструкцию ниже.
Выберите img_gear
в иерархии и откройте окно Анимация. Создайте новый клип, нажав [Create New Clip]
, и назовите его gear_rotate_up
. Сохраните клип в папке Animations.
Теперь отметьте 1:00
на временной шкале. Затем в Инспекторе измените Rotation Z
на 360.
Остановите запись, нажав на кнопку с красным кружком.
Теперь откройте папку Animations
в Браузере проектов и выберите gear_rotate_up
. В Инспекторе снимите галку с Loop Time
(Зацикливание).
Теперь пришло время настроить состояния. Выберите img_gear
в Иерархии, откройте вкладку Аниматор, а затем выполните следующие действия:
- Дублируйте состояние
gear_rotate_up
путем копирования и вставки его.
- Переименуйте копию в
gear_rotate_down
и измените его скорость Speed
на -1 В Инспекторе.
- Добавьте новый булевский параметр по имени
isHidden
и присвойте ему значение true
.
- Создайте два переходы между состояниями. В условиях, установите
isHidden == true
для перехода из gear_rotate_up
в gear_rotate_down
и isHidden == false
для обратного перехода.
Наконец, поскольку нам не нужно, чтобы шестеренка вращалась после запуска сцены, выберите img_gear
в Иерархии и отключите компонент Animator
.
Включение анимации с помощью кода
Для завершения раскрывающегося меню, вам нужно вызвать анимацию вращения шестерни с помощью всего нескольких строк кода. Откройте UIManagerScript
в MonoDevelop и добавьте следующие переменные экземпляра:
public Animator gearImage;
Проскрольте вниз и найдите ToggleMenu
. Добавьте следующие строки в нижнюю часть тела метода:
public void ToggleMenu()
{
//..пропущено..
gearImage.enabled = true;
gearImage.SetBool("isHidden", !isHidden);
}
Это делает доступным компонент аниматора и устанавливает для его параметра isHidden
то же значение, что и для параметра isHidden
аниматора панели содержания. Сохраните скрипт и вернитесь обратно в Unity.
В Unity выберите UIManager в Иерархии. Перетащите img_gear в поле Gear Image
в Инспекторе.
Запустите сцену и полюбуйтесь как вращается ваша шестеренка!
Отличная работа! Выезжающее меню готово и сцена начинает напоминать единое целое. Мы не будем останавливаться на кликах по кнопкам меню, ведь вы уже должны уметь управляться с событиями пользовательского интерфейса, а интеграция Game Center фактически сведет этот мануал на нет. Вместо этого мы апгрейднем сцену из RocketMouse, построенную на старом GUI, так, чтобы она работала на новом GUI.
Если вы не завершили изучение этого урока, - ничего страшного. Наоборот, у вас появился шанс узнать гораздо больше о новой системе GUI. Вам не придется глубоко погружаться в код или изучать механику игры. Все, что вам предстоит сделать, - это заменить метод OnGUI
.
Обновление сцены RocketMouse для использования нового GUI
Как уже упоминалось в части 1 урока, как только вы перешли на Unity 4.6, вы можете забыть метод OnGUI
как плохой сон. В игре RocketMouse, несколько элементов пользовательского интерфейса использовали этот старый метод для отображения набранных очков и кнопки для перезапуска игры. Их-то нам и предстоит заменить.
Добавляем Points Label
Переключитесь на сцену RocketMouse и откройте папку Scenes в Браузере проекта. Дважды щелкните на сцене RocketMouse, чтобы открыть ее. Выберите GameObject\UI\Text
, чтобы создать новый текстовый элемент пользовательского интерфейса.
Выберите Text
в Иерархии и сделайте следующие изменения в Инспекторе:
- Переименуйте его в
txt_points
.
- Якоря установите в top-left.
- Координаты точки вращения -
Pivot
- пусть будут (0, 0.5).
- Задайте
Pos X
равной 50, а Pos Y
равно -30.
- Измените
Text
но 0, так как игрок начинает с нулевыми очками.
- Откройте папку
Fonts
в Браузере проектов и перетащите TitanOne-Regular в пале Font
в Инспекторе.
- Размер шрифта
Font Size
сделаем равным 24.
- Установите
Horizontal Overflow
(метод, используемый для случая, когда текст слишком широкий, чтобы поместиться в прямоугольнике.) в Overflow для того чтобы могли отображаться огромные числа.
Кроме того, не забудьте изменить цвет текста на белый цвет.
Добавление иконки очков игрока
Сейчас у нас счет просто отображается числами, но этого не достаточно. Вы должны быть уверены, что игрок сразу увидет его, не блуждая взглядом по экрану. Да, нынешние игроки избалованы впечатляющим интерфейсом даже в простейших приложениях, поэтому добавим иконку, чтобы добавить шарму. Выберите GameObject\UI\Image
, чтобы создать новое изображение. Выделите его в Иерархии и выполните следующие действия:
- Переименуйте его в
img_points
- Перетащите его на
txt_points
, чтобы добавить его как дочерний элемент – когда вы будете двигать метку, иконка тоже будет двигаться.
- Установите Якоря на middle-left.
- Координаты точки вращения Pivot будут (1, 0.5).
- Длину
Width
и ширину Height
сделаем равной 32.
- Для
Pos X
установим значение -5, а для Pos Y
- 0.
- Откройте папку
Sprites
в браузере проекта и перетащите картинку в поле Source Image
в Инспекторе.
На этот раз вы используете изображение из папки спрайтов, поэтому не нажимайте кнопку Set Native Size
, поскольку это будет изображение, используемое в игре для монет, и оно немного больше, чем иконка.
Обновление Points Label
В учебнике по игре большая часть кода содержится в скрипте MouseController.cs
, так что вы будете редактировать его, чтобы обновлять points label. На самом деле, до конца этого урока вы будете работать только с этим скриптом.
Самым лучшим вариантом было бы разбить этот огромный скрипт на несколько более мелких кусочков. Но тогда вам потребуется анализировать существующий код. Поэтому мы поработаем с этой простыней, тем более, что нам нужно просто сделать небольшие изменения и двигаться дальше.
Откройте папку Scripts
в Браузере проекта и дважды щелкните на скрипте MouseController
чтобы открыть его в MonoDevelop. Когда скрипт отобразится, найдите и удалите методы, которые используются в старом GUI:
onGUI
DisplayCoinsCount
DisplayRestartButton
Добавьте следующий код, используя директиву using
:
using UnityEngine.UI;
После этого, добавьте следующую переменную экземпляра, содержащую ссылку на метку:
public Text coinsLabel;
Наконец, добавьте следующую строку в конце кода CollectCoin
, который вызывается каждый раз, когда мышь собирает монетки.
coinsLabel.text = coins.ToString();
Сохраните скрипт и вернитесь обратно в Unity. В Unity выберите mouse
в Иерархии и перетащите txt_points
на поле Coins Label
в Инспекторе.
Запустите сцену и отправьте мышь на поиск монеток. Вы должны увидеть обновление ярлыка при собирании монет.
Все выглядит хорошо, но вы, возможно, заметили одну проблему. Когда вы удалили старые методы onGUI
вы также удалили кнопку, отображаемую когда мышь умирает, поэтому игрок не сможет перезапустить игру!
Добавление диалога перезапуска.
Я думаю, что вы уже как следует освоили новую систему GUI и может создать этот диалог без меня. Нужно создать панель с меткой и две кнопки, которые выглядят так:
После чего поместить ее в центре холста.
Попробуйте сделать все это сами, а если у вас не получается, то читайте текст ниже.
- Создайте новую Панель, используя
GameObject\UI\Panel
и переименуйте ее в dlg_restart
.
- Установите Якоря в
middle-center
.
- Для
Width
и Height
установите значение 200, а для Pos X
и Pos Y
- 0.
- Используйте изображение
settings_panel_bg_9slice
из папки Menu
в качестве источника изображения (Source Image) для Панели.
- Дважды щелкните на поле
Color
в Инспекторе и установите прозрачность A
равной 255. Это сделает нашу Панель не прозрачной.
- С помощью следующей последовательности действий
GameObject\UI\Text
создайте текстовый элемент и переименуйте его в lbl_youlose
.
- Перетащите
lbl_youlose
на dlg_restart
, чтобы добавить его в качестве дочернего элемента.
- Установите его Якоря в
top-center
, Pos X
- 0 and Pos Y
- -40.
- Воспользуйтесь шрифтом
DCC-Dreamer
из папки Fonts. Размер шрифта (Font Size) сделайте равным 30.
- Сделайте выравнивание
Alignment
по центру и Horizontal Overflow
в Overflow.
- Измените
Text
на фразу Ты проиграл :[
- Устраните прозрачность дважды кликнув на
Color
и установив значение A
равным 255.
- Создать новую кнопку, используя
GameObject\UI\Button
и переименуйте ее в btn_restart
.
- Перетащите ее на
dlg_restart
чтобы добавить в качестве потомка.
- Установите Якоря в
top-center
, Pos X
в 0
, а Pos Y
в -100
.
- Установите ширину
Width
равной 135
, а высоту Height
равной 45
.
- Используйте
btn_9slice_normal
в качестве источника изображения - Source Image
.
- Выберите вложенный текстовый элемент и сделайте его шрифт
Font
таким - TitanOne-Regular, размер шрифта Font Size
- 18, а цвет Color
полностью белый (без прозрачности). В Инспекторе значение поля Text
замените на Restart.
- Чтобы создать вторую кнопку, просто щелкните правой кнопкой мыши на
btn_restart
и выберите Duplicate
(дублировать). Назовите дубль btn_exit
. Установите его Pos Y
равной -160. Затем выберите вложенный текстовый элемент и изменить его Text
на Выход.
Отображение диалогового окна с перезапуском
Мы не будем анимировать внешний вид окна, поскольку вы уже наверняка знаете, как это делать, и повторять одно и то же просто нет смысла. На этот раз, вы будете прятать диалог в начале игры и показывать его когда игрок проигрывает. Откройте скрипт MouseController
в MonoDevelop и добавьте следующую переменную экземпляра:
public GameObject restartDialog;
Затем добавьте следующую строку кода в Start
чтобы скрыть диалоговое окно при старте:
restartDialog.SetActive(false);
Прокрутите вниз и добавить следующую строку в конце HitByLaser
:
restartDialog.SetActive(true);
Как вы, наверное, догадались, метод HitByLaser
вызывается когда мышь умирает. Следовательно, это идеальное место, чтобы открыть диалоговое окно перезагрузки. Добавьте следующие два метода для перезапуска и выхода из игры:
public void RestartGame()
{
Application.LoadLevel (Application.loadedLevelName);
}
public void ExitToMenu()
{
Application.LoadLevel ("MenuScene");
}
Через минуту мы привяжем их к соответствующим кнопкам. Сохраните файл со скриптом и переключитесь обратно в Unity. В Unity выберите в Иерархии mouse
и перетащите dlg_restart
на поле Restart Dialog
в Инспекторе.
Затем выберите btn_restart
в Иерархии и прокрутите список вниз до On Click (Button)
. Нажмите +
чтобы добавить новый элемент. После этого перетащите mouse
из Иерархии в новый элемент. В выпадающем списке функций выберите MouseController\RestartGame ()
.
Теперь, выберите btn_exit
и проделайте все тоже самое, но на этот раз выберите функцию MouseController\ExitToMenu ()
. Запустите сцену и наведите мышка на лазерную линию огня. Вы должны увидеть диалоговое диалоговое окно, появляющееся после смерти мыши. Если вы нажмете на кнопку Restart
, вы перезапустите игру. Нажатие на кнопку Exit
приведет к возврату в главное меню.
Вот и все! Поздравляю с завершением чтения этого учебника! Вы можете скачать окончательный проект здесь: RocketMouse_Final. Я надеюсь, что вам понравилась новая GUI и вы с энтузиазмом приметесь создавать интересные пользовательские интерфейсы в играх! Удачи!