unity panel что такое
Организация интерфейса в Unity с UI Canvas
В Unity есть хорошая система для создания пользовательского интерфейса UI Canvas. По ней написано довольно много обучающего материала, но большинство гайдов рассказывает только о том, какие кнопки нажать и какой код написать, чтобы все заработало. В качестве примеров обычно приводится небольшой интерфейс состоящий из пары окон: главное меню, настройки. Однако в играх бывает гораздо больше окон и когда их становится уже хотя бы десяток, возникает необходимость какой-либо их организации. В рамках этой статьи я хочу рассказать как я решаю эту проблему.
Для начала нужно выделить отдельные окна в вашем интерфейсе. Под окном я подразумеваю панель с некоторыми контролами.
У каждого окна должен быть корневой объект, который будет содержать все контролы. Этот объект будет представлять окно как единое целое. Например есть панель на которой находятся элементы управления, логично сделать эти элементы дочерними по отношению к панели. К каждому окну прикрепляется компонент, котрый является наследником абстрактного класса Window.
Window
Window написан исходя из того, что у окон могут быть дочерние окна, т.е. те окна которые могут быть открыты из текущего окна при этом в один момент времени может быть открыто одно дочернее окно, а все остальные должны быть закрыты. С этой целью класс содержит свойство CurrentWindow в котором хранится ссылка на открытое на данный момент окно. А также есть событие OnOpen которое сообщает об открытии окна. Метод ChangeCurrentWindow() можно подписать на это событие у дочерних окон, чтобы в любой момент времени было открыто одно дочернее окно, он закрывает открытое дочернее окно и меняет ссылку на текущее открытое окно, ниже я приведу пример реализации. Также в классе есть методы SelfClose() и SelfOpen(), эти методы отвечают за то как будет открываться и закрываться окно. В методе Awake() происходит регистрация окна в UIManager, т.е. добавляется ссылка на окно.
UIManager
Далее перейдём к классу UIManager, он является sigleton-классом для того чтобы все окна могли к нему обращаться при необходимости. Как видно в нём есть список окон Windows, именно в нем хранятся ссылки на все окна на сцене. InitUI() нужен чтобы что-либо инициализировать, например, если вы хотите создавать окна из префабов, то здесь вы можете сделать их инстансы.
В методе Start() вы можете открыть окна которые должны быть открыты с самого начала или наоборот закрыть ненужные. Метод Get() позволяет получить ссылку на конкретное окно.
SettingsWindow
В качестве примера приведу свою реализацию окна настроек:
Из окна настроек я могу открыть 4 других окна, чтобы открыто было только одно окно, я подписываю метод ChangeCurrentWindow() окна настроек на события OnOpen дочерних окон, таким образом открытые окна закрываются, при открытии других. Реализации SelfOpen() и SelfClose() просто активируют или деактивируют окно.
Таким образом получается легко расширяемая система UI, нет необходимости вручную добавлять ссылки на окна в инспекторе или где-либо еще, чтобы добавить новое окно, нужно всего лишь создать соответствующий класс и унаследовать его от Window. У такой системы есть пара минусов, это то, что чем больше окон, тем больше классов необходимо будет создать и то, что поиск ссылки на окно происходит путем перебора массива ссылок, но на мой взгляд эти недостатки окупаются преимуществами.
Создание панели умений. Часть 1. Работа с Unity UI.
Введение
Данной статей начинается серия публикаций о создании панели умений (skills panel) для вашей игры. Панели умений встречаются во многих RPG играх и не только.
По мере создания панели умений будет рассмотрено много вспомогательных компонентов, таких как работа с пользовательским интерфейсом или Unity UI (user interface); использование компонентов Event System, Grid Layout Group, Outline; настройка Canvas; использование интерфейсов IPointerDownHandler, IPointerEnterHandler, IPointerExitHandler; и многое другое. В результате получится вот такая игра:
Поскольку материал вышел довольно объёмным, то пришлось разделить его на части. Сегодня особое внимание уделим работе с Unity UI и настройкам Canvas.
Создание сцены и настройка Canvas:
Сначала нужно создать пустой 3d проект и добавить новую камеру для UI (GameObject > Camera), дадим ей имя UICamera. Изменим проекцию (projection) камеры на orthographic (размер объектов не зависит от расстояния). Выставим Clear Flags > Depth only, это даст прозрачную камеру без лишних фоновых добавлений. Поскольку UI должен обрисовываться поверх всего, то нужно изменить глубину камеры (Depth = 1).
Далее создадим Canvas (GameObject > UI > Canvas), вмести с элементом Canvas создастся Event System, он необходим для обработки событий, которые происходят на Canvas (более подробно рассмотрим позже). Что же такое Canvas и для чего он нужен. Canvas переводится как «Холст» и представляет собой абстрактное пространство для настройки и отрисовки UI. Все UI элементы должны быть потомками Canvas. Рекомендуется использовать следующие настройки (они позволят автоматически подстраиваться под расширение экрана, очень удобно для мобильных устройств):
Выбираем «Render Mod > Screen Space – Camera»UI. В поле «Render Camera» выбираем созданную нами UICamera. Далее остается изменить Canvas Scaler Sctipt, а именно поле «UI Scale Mode > Scale With Screen Size», что дает автоматическое изменение UI в зависимости от расширения экрана.
На этом настойки Canvas закончены.
Работа с Unity UI:
Работать с UI элементами удобно в 2d режиме (это не обязательно, но значительно упростит процесс разработки UI), переключаться между 2d и 3d режимами можно «Scence > 2D».
Все элементы UI содержат следующий компонент «Rect Transform» (в том числе и Canvas). Именно «Rect Transform» контролирует расположение UI относительно расширения экрана.
Тема связана со специальностями:
Четыре треугольника называют «Якорь», поскольку в зависимости от его расположения и настроек изменяют свое поведение UI элементы при изменении расширения экрана. Синий круг – это «центр» кнопки (или другого UI элемента), относительно него происходит вращение (Rotation) или масштабирование (Scale) элемента.
Место расположения «центра» кнопки хранится в специфическом формате и за него отвечает поле «Pivot». Где хранится расположение «центра» в соотношении (координаты «центра» x и y поделить на ширину и высоту соответственно) относительно нижнего левого угла. То есть соотношение сторон зеленого и красного квадратов на рисунке ниже.
Например, «Pivot X = 0.5, Y = 0.5» означает, что центр кнопки находится посередине кнопки. «Pivot X = 0, Y = 0» означает, что центр кнопки находится в левом нижнем углу.
Далее рассмотрим работу «Якоря», он может работать в 2-х режимах.
Pos X, Pos Y, Pos Z отвечают за расстояние между центром «Якоря» и «центром» UI элемента.
Возникает вопрос, а зачем нам нужен этот «Якорь». Ответ прост, при изменении размеров родительского UI элемента «Якорь» изменяет расстояние к «центру» текущего UI элемента пропорционально этим изменениям. «Якорь», как и «центр», хранит свои координаты в соотнесённом виде в поле Anchors.
Для режима 1 «Anchors > Min» и «Anchors > Max» совпадают. Очень важно запомнить, что в этом режиме изменяется только расстояние между «Якорем» и «центром», а поля Width, Height остаются низменными (поскольку Canvas настроен в режиме «Scale With Screen Size», то с изменением расширения экрана все UI элементы изменят свои размеры за счет автоматического изменения параметра Scale в самом Canvas).
Изменяя значения этих полей, меняется размер UI элемента, а не «Якоря». За «Якорь» по-прежнему отвечает поле Anchors, но теперь «Anchors > Min» и «Anchors > Max» не всегда будут совпадать.
Краткий обзор нового Unity UI с примерами организации интерфейса
Пожалуй, для многих новость о выходе новой системы Unity UI (далее просто UI) не показалась чем-то значимым. Как минимум — по причине её сырости, как максимум — из-за существования NGUI. Я поначалу не стал исключением, но открытие исходного кода UI системы (1) под либеральной лицензией MIT/X11, а так же энтузиазм разработчиков Unity Technologies заставили меня изменить мнение.
На мой взгляд, новый UI принесет нам довольно много плюсов:
Давайте перейдем к конкретике. Начну с общего представления, сформировавшегося после раскуривания скудной документации, просмотра видео-уроков и раскопки исходного кода.
Концепция UI
Подход к организации интерфейса переработан впринципе. То есть если вы ранее работали с GUI, в новом UI вы почти не найдете ничего похожего. И наоборот — если вы работали с NGUI, то найдете очень много общего. В целом ее можно назвать типичной для сред с инструментами визуальной разработки.
В основе понимания новой концепции лежат три компонента: Canvas, Rect Transform и Event Trigger.
Canvas — является контейнером для всех элементов UI и определяет режим рендера. Таких контейнеров на сцене может быть более одного (3).
Rect Transform — этот компонент позволяет задать положение и размер игрового объекта, используя удобные визуальные контролы. Он вводит понятия ширины и высоты, а не только масштаб (4).
По мере знакомства с UI я создавал для себя возможные варианты использования. Давайте на них и разберем эту всю кухню. В конце статьи вы можете найти демо-проект, на который я буду ссылаться в тексте. К сожалению, этим примерам далеко до готовых рецептов, так как они не достаточно проработаны, плюс заточены под 2D игры, хотя местами вполне подойдут и для 3D.
Пример #1
Цели:
1. Тайловый фон;
2. Фиксированное положение контролов в независимости от разрешения и соотнешения сторон экрана;
3. Контролы должны быть пропорциональны размеру экрана.
Пример #2
Цели:
1. Ориентация строго портретная;
2. Универсальный для всех соотношений сторон фон, который всегда отображается на весь экран, а если необходимо обрезается только снизу;
3. Фиксированное положение контролов в независимости от разрешения и соотнешения сторон экрана;
4. Контролы должны быть пропорциональны размеру экрана.
Пример #3
Цели:
1. Ориентация строго портретная;
2. Тайловый фон, который не скейлится;
3. Фиксированное по размеру игровое поле, например 400×400;
4. Фиксированное положение контролов в независимости от разрешения и соотнешения сторон экрана;
5. Контролы должны быть пропорциональны размеру экрана.
Вариант решения:
1. Можно, конечно, реализовать фон как Sky Box или игровым объектом типа Quad с затайленой текстурой и размерами заведомо больше экрана. Но мы пойдем UI-ным путем и создадим Canvas, аналогичный примеру #1, только выставим тип рендера Screen Space — Camera и пропишем нашу главную камеру в поле Render Camera;
2. Теперь создадим еще один Canvas с типом рендера World Space, пропишем камеру и поставим значение Order in Layer равное 1, что бы этот слой рисовался поверх предыдущего Canvas у которого это значение равно 0;
3. Советую вам при рендере World Space _заранее_ ставить значение масштаба Canvas таким образом, что бы у вас не было проблем с размером шрифтов;
4. Контролы раставляем уже известным нам способом.
Пример #4
Цели:
1. Создать скроллер;
2. Контент не должен быть виден за пределаеми скролера;
3. Он должен скейлиться вместе с экраном и липнуть к нижнему краю.
Пример #5
Конечно, эти примеры покрывают лишь малую часть возможных задач и реализаций, но я надеюсь, они помогут вам выбрать удобное направление для поисков решения или, как минимум, песочницу, в которой можно попробовать разные варианты.
Как создать внутриигровое меню в Unity
Создание и дизайн главного меню и меню настроек
1. Создаем две сцены: Menu и Game
2. Открываем File->BuildSettings и перетаскиваем созданные сцены в Scenes in build.
Теперь можем приступать к созданию пользовательского интерфейса. Откройте сцену Menu и добавьте Panel. Сразу добавляется Canvas(Холст) и дочерним объектом к нему добавляется Panel (Панель).
Обратим внимание на инспектор для Canvas. А именно на компонент Canvas.
Render Mode автоматически выставлен на Screen Space – Overlay.
Screen Space – Overlay:
Способ рендеринга, при котором Canvas напрямую привязан к экрану. Если изменить разрешение экрана или размер, то Canvas с такой настройкой тоже изменит свой масштаб на подходящий. UI в таком случае будет отрисовываться поверх других объектов.
Важен порядок размещения объектов в иерархии. Холст Screen Space – Overlay должен находиться в самом верху иерархии, иначе он может пропасть из виду.
Screen Space – Camera:
В таком случае, Холст прикрепляется в камере. Для такой настройки обязательно нужно указать камеру которой соответствует Холст. Как и в предыдущем пункте, Холст будет менять свой масштаб в зависимости от разрешения и размера экрана, а также от области видимости камеры.
Так же для Холста с такими настройками важно размещение относительно других объектов. На переднем плане будут объекты, которые находятся ближе к камере, не зависимо от того, это UI или другие GameObjects.
Холст размещается, как любой другой объект без привязки к камере или экрану, он может быть ориентирован как вам угодно, размер Холста задается с помощью RectTransform, но то, как его будет видно во время игры, будет зависеть от положения камеры.
В данном задании мы будем использовать Screen Space – Overlay.
Давайте настроим цвет панели. Можно также добавить картинку на фон. Для этого нужно обратить внимание на компонент Image в Инспекторе панели.
Как видите, картинка добавляется в поле Source Image. Картинку можно просто перетащить из файлов проекта, либо кликнуть на кружочек справа от поля.
Цвет выбирается в поле Color, либо с помощью инструмента пипетки.
Важно знать, что пипетка позволяет выбрать цвет за пределами Unity.
После того, как выбрали цвет или картинку, нам нужно разместить кнопки, которые всем будут управлять, а так же текст. Чтобы упростить себе задачу, для Panel мы добавим еще один компонент, который называется Vertical Layout Group. И сразу настроим его.
Нам необходимо разместить все кнопки и текст по центру экрана. Для этого находим в компоненте Vertical Layout Group пункт Child Alignment и выбираем Middle Center. Теперь все наши элементы, будь то кнопки или текст, будут выравниваться по центру, независимо от разрешения экрана.
Так же убираем галочки с ChildForceExpand. Должно получиться так:
Данный компонент можно настраивать в зависимости от того, какой вид вы хотите получить.
В нашем меню должны быть следующие кнопки:
1. Start Game
2. Settings
3. Exit
Сейчас, добавляем Text дочерним элементом нашей Панели. Можете заметить, как он прикрепляется по центру. Иногда для этого требуется созданный элемент в окне Scene просто передвинуть на Panel и тогда он выровняется. Настраиваем текст так, как хочется с помощью компонента Text(Script) в инспекторе.
После добавляем Button. Кнопка добавится под текст.
Разберем компонент Button нашей кнопки. Нас интересует Transition – то, как кнопка будет реагировать на действия мышки. В Unity реализовано несколько способов. Пока рассмотрим довольно простой Color Tint. Это значит, что кнопка будет менять свой цвет при определенных состояниях. Интерфейс для настройки довольно удобный. Настраиваем так, как нравится.
Так же у объекта Button есть дочерний объект Text – это текст который будет отображаться на кнопке. В тексте прописываем Play.
Кажется, Текст и Кнопки находятся слишком близко друг к другу.
Что бы это исправить для нашего Текста Menu добавляем еще один компонент, который называется Layout Element. И ставим галочку напротив Ignore Layout.
После этого выставляем Anchor на Middle-Center.
Потом добавляем еще три кнопки и называем их Settings, Credits, Exit.
Можно поменять размеры кнопок. На этом этапе меню выглядит так:
Переходы между main menu и settings
Что бы переходить на меню опций не обязательно делать новую сцену.
Для начала создаем пустой GameObject (Create Empty) как Child нашего Холста. Назовем его Main menu. Потом нашу панель, со всеми инструментами сделаем дочерними элементами этого объекта. Должно получиться так:
Выбираем наш MainMenu объект и сделаем его дубликат. С выбранным элементом нажимаем комбинацию клавиш Ctrl+D. У нас появится новый объект.
Переименовываем новый объект в Settings. Для удобства управления инактивируем MainMenu.
Дальше в панели Settings переписываем текст на Settings, а так же удаляем все кнопки.
В настройках мы сделаем следующее – Fullscreeen, настройки громкости, качество изображения, разрешение экрана.
За контроль Fullscreen будет отвечать элемент Toggle.
За громкость – Slider.
За качество изображения и разрешение – Dropdown.
Между каждыми элементами следует разместить текст, который будет обозначать название каждой настройки. Следует также добавить кнопку, которая будет возвращать нас обратно в главное меню.
Можно настроить Spacing в Vertical layout group, чтобы между элементами было немного пространства. Добавим на панель картинку и в итоге получим такой результат:
Программирование кнопок
Перейдем к написанию скрипта меню.
Нам нужно, чтобы по нажатию кнопки Play у нас запускалась другая сцена с нашей игрой, а по нажатию кнопки Exit игра закрывалась.
Это мы и пропишем в нашем скрипте.
Для MainMenu добавляем новый компонент MenuControls.cs и отрываем его.
Первое что надо сделать – удалить существующие методы Start() и Update() – тут они нам не нужны.
Дальше нам надо подключить следующее:
После этого напишем свой метод для нажатия кнопки Play. Метод должен быть public — нам нужно иметь возможность видеть его за пределами нашего скрипта.
За загрузку сцены отвечает SceneManager и у него есть метод LoadScene. Существует несколько перегрузок метода. Можно передавать имя сцены, которую вы хотите загрузить. В нашем случае это сцена «Game».
В итоге функция будет выглядеть следующим образом.
Так же создаем метод для выхода из игры:
Однако в Unity мы не увидим результата работы этого метода, так как подобное работает только в билде. Для того что бы проверить, что все работает правильно, добавляем в метод строчку
Теперь необходимо прикрепить события кнопок к этим методам. Выбираем кнопку Play и находим в инспекторе следующее:
Это событие кнопки, которое по нажатию будет вызывать подписанные на событие методы. Добавляем метод нажимая на +.
В появившееся окно нужно перетащить объект, в котором содержится нужный скрипт. В нашем случае это Main Menu.
После этого нужно выбрать скрипт MenuControls и найти метод PlayPressed().
Точно также делаем для кнопки Exit. Только теперь выбираем метод ExitPressed().
Для кнопки Settings нам не нужно писать никакой код, так как некоторый функционал уже встроен.
Суть в том, что мы будем активировать GameObject. На этом этапе у вас должен быть активным MainMenu, а Settings не должно быть видно. Так же видим, что когда мы активируем Settings, он полностью перекрывает Menu. Суть в том, что играет роль порядок расположения дочерних объектов Холста – в каком порядке они расположены в иерархии в том порядке они и будут прорисовываться. Поскольку Settings у нас находятся над Main Menu, то они перекрывают меню.
Это мы и будем использовать.
Ну а для кнопки Back, которая находится в меню опций, можно таким же образом подключить событие SetActive для объекта Settings, но на этот раз нам нужно инактивировать наш объект, поэтому мы просто не ставим галочку.
Вот и все, мы закончили создание меню, а в следующей части продолжим и сделаем так, чтобы игра реагировала на изменения настроек.
Настройки
Настройки полного экрана
Первое что мы пропишем это переключение полноэкранного и оконного режимов.
Нужно убрать галочку с пункта Is On нашего Toggle элемента.
Создаем скрипт для объекта Settings. Назовем его Settings.cs.
Для начала нам надо хранить переменную типа bool которая будет отображать текущее состояние – полноэкранный режим или нет. А потом, по изменению toggle эта переменная будет переключаться на противоположное значение.
У экрана есть свойство Screen.fullScreen типа bool. Можно просто будем присваивать значение нашей переменной isFullScreen этому свойству.
Увидеть результат можно только в билде. Давайте сейчас это сделаем. Учтите, что для того что бы билд был правильным нужно оставить активным только объект MainMenu, а Settings отключить. Если это сделано, то запускаем билд через File->BuildSettings и нажимаем кнопку Build.
После этого можно проверить работу программы. Если все правильно, то по нажатию галочки сразу будет изменяться режим.
Изменения громкости звука в игре
Для работы с настройками звука нам для начала понадобится AudioMixer, а также какой-нибудь трек, на котором мы будем проверять работу наших настроек.
Называем его GameSettings. После этого открываем окно AudioMixer: Window->Audio Mixer (Ctrl + 8).
Что бы контролировать параметры миксера через скрипт, их нужно сделать видимыми для этого скрипта. Эта процедура называется ExposeParameters. Для этого кликаем на Mixer и в инспекторе находим volume и кликаем правой кнопкой мыши. Выбираем Expose to script:
Теперь в окне Audio Mixer обратите внимание на пункт Exposed Parameters в верхней левой части.
Теперь там есть параметр. Кликаем на него и называем наш параметр masterVolume. Следует запомнить имя, которое ему присваиваем – его нужно будет указать в коде.
Переходим в Settings.cs и создаем поле AudioMixer, чтобы получить ссылку на него в коде.
потом создаем метод
Метод SetFloat будет принимать значения нашего слайдера и присваивать это значение параметру “masterVolume”.
Осталось прикрепить наш метод к событиям слайдера. Находим в инспекторе слайдера поле On Value Changed и точно так же прикрепляем объект. Вот только теперь нам надо не просто выбирать метод из списка, а использовать поле Dynamic float. Как видите, там уже есть наш метод, и он будет получать переменную от самого слайдера. Также нужно не забыть перетащить AudioMixer в соответствующее поле в компоненте Settings.cs.
Теперь добавим звуки в нашу игру, чтобы проверить работу скрипта.
На canvas добавим компонент Audio Source.
Настроим его следующим образом:
Audio Clip – саундтрек
Output – Мастер нашего миксера (дочерний объект)
Loop – поставить галочку – зациклить композицию, чтобы она играла постоянно.
Качество изображения
В Unity уже встроены настройки качества изображения. Edit->Project Settings->Quality. В инспекторе видим Quality settings. Их можно добавлять и настраивать.
Особенностью работы с настройками качества является следующее:
Каждой настройке соответствует индекс, который мы можем получить из Dropdown. Все что нужно сделать – переписать соответствующие пункты в нужные индексы в нашем UI элементе. Открываем его и в инспекторе находим Dropdown(Script) и в нем пункт Options. Дальше вписываем настройки в нужном порядке. У меня получилось так:
Дальше нужно прописать код. Мы продолжаем дополнять методами наш скрипт Settings.cs
Создаем метод, который будет принимать int – индекс выбранного пункта.
Сохраняем скрипт и подключаем метод к событию на нашем меню. На этот раз это событие Dropdown – On Value Changed.
Поскольку наш метод будет получать значение от самого UI элемента, то мы выбираем название метода из группы Dymanic int. по аналогии с предыдущим пунктом.
Разрешение экрана
Экраны у всех разные и наперед угадать какие разрешения на них будут поддерживаться невозможно. Поэтому для настроек разрешения экрана нужно сначала получить все возможные разрешения, а потом заполнить список разрешений этими значениями.
Первое что нам понадобится – массив типа Resolution[] где мы будем хранить значения разрешений экрана.
Однако для пунктов выпадающего списка тип – string. Поэтому создаем список List<> в который мы будем сохранять значения возможных разрешений. Для работы со списками необходимо подключить:
Также нам понадобится ссылка на соответствующий Dropdown. Для работы с UI элементами следует также прописать:
В скрипте получим следующие поля:
Инициализацию и заполнение проводим в методе Awake. Этот метод вызывается при запуске объекта, соответственно выполняется раньше, чем все остальные методы.
Получаем значения и каждое из них добавляем в List в формате ширина*высота. После этого очищаем список Dropdown и заполняем его новыми опциями.
Теперь нужно создать метод, который будет менять разрешение экрана. Как и в предыдущих пунктах – принимать значение будем от UI элемента. Создаем функцию, которая принимает int
В SetResolution необходимо передать параметры – ширина, высота и булевскую переменную, отвечающую за полный экран. У нас такая уже есть – это isFullScreen. Передаем ее в функцию.
Дальше не забываем подключить к соответствующему событию наш метод Resolution из группы Dynamic Int, а так же добавить ссылку на нужный Dropdown.
Готово. Теперь можно использовать это меню вместо скучного дефолтного лаунчера. Однако, чтобы был толк нужно отключить его запуск.
Edit->ProjectSettings-> Display Resolution Dialog-Disabled