На днях начал изучать новый UI в Unity 4.6 beta. Все, что на официальном сайте в видео туториалах, естественно было просмотрено, но там нет ничего о том, как работает новый UI. Доков я тоже не увидел и, естественно, захотелось разобратьс, я как это все работает. Итак, кратко о том, что я понял:
Исходя из исследований методом тыка основным объектом, без которого построение UI невозможно, является Canvas. Он отвечает за отрисовку элементов интерфейса и проброс событий к ним. Так же у Canvasесть 3 варианта отрисовки UI: ScreenSpace — Overlay, ScreenSpace — Camera и WorldSpace.
ScreenSpace — Overlay и ScreenSpace — Camera
Как видно из названия режимов, они работают с экранными координатами. Это позволяет собирать PixelPerfect интерфейс, но если вам нужно, чтобы интерфейс выглядел одинаково на всех разрешениях, или вы хотите создать 3D UI — эти варианты вам не подходят.
WordlSpace
Этот режим отрисовывает элементы в мировом пространстве, так что если у вас нет камеры, в которую они будут попадать, то вы их можете не увидеть. Этот режим меня заинтересовал, так как позволяет создавать UI, который будет выглядеть одинаково — независимо от разрешения экрана. Единственная небольшая проблема — это то, что Canvas, в отличие от предыдущих режимов, не реагирует на изменение аспекта экрана. Но эта проблема решается простым скриптом, управляющим шириной/высотой канваса при старте.
using UnityEngine;
using System.Collections;
public class CanvasHelper : MonoBehaviour
{
private const float ETHALON_2x3_LANDSCAPE = 1.3333333333333f;
private const float ETHALON_2x3_PORTRAIT = 0.666666666666f;
public Canvas canvas;
// Use this for initialization
void Start ()
{
var ethalon = Screen.orientation == ScreenOrientation.Landscape ? ETHALON_2x3_LANDSCAPE : ETHALON_2x3_PORTRAIT;
var cam = canvas.worldCamera;
var rectTransform = canvas.transform as RectTransform;
var delta = rectTransform.sizeDelta;
if (Screen.orientation == ScreenOrientation.Landscape)
delta.x *= cam.aspect / ethalon;
else
delta.y *= cam.aspect / ethalon;
rectTransform.sizeDelta = delta;
}
}
Отдельные элементы я описывать не буду, все равно с ними можно ознакомиться методом математического тыка. А вот на систему сообщений стоит взглянуть поподробнее.
Чтобы ваш UI работал, необходимо иметь на сцене EventSystem. EventSystem — это компонент, который занимается обработкой событий пользователя и передачей их в UI. Обработка событий происходит в InputModule компонентах. Я встретил 2 (StandaloneInputModule для ПК, консолей и веба и TouchInputModule для мобильников и планшетов). Причем, судя по их настройках, они могут хотя бы частично быть взаимозаменяемыми.
InputModule отлавливает события пользователя и передает их в EventSystem, которая уже направляет все это дело в UI. Но как же определяется, был ли нажат активный элемент? За это отвечает GraphicRaycaster.
GraphicRaycaster
Этот компонент находится на Canvas-е и в ответ на нажатие мыши/тач определяет, какому объекту надо послать событие. Всего в новом UI есть 3 типа рэйкастеров: рэйкастер для 2D физики, рейкастер для 3D физики и рэйкастер для графических элементов. По умолчанию на гейм объект добавляется последний.
У этого рейкастера есть один огромный недостаток: чтобы объект получил событие, он должен иметь графическую составляющую. Другими словами, если вы хотите создать прозрачную область экрана, которая будет запускать то или иное действие по нажатию, вам придется создавать компонент с графикой и делать его полностью прозрачным. По-моему, это очень неудобно, хорошо, что есть возможность расширить эту систему введением новых рейкастеров.
Немного о коде
Систему UI можно разделить на 3 части: система генерации событий (UnityEngine.Events) — нововведение в Unity 4.6, затрагивает не только UI, но и системы физики и рендера, система отлова событий (UnityEngine.EventSystems) и непосредственно логику UI (UnityEngine.UI). Причем первая система является частью основной билиотеки движка, а остальные — 2 частью библиотеки UI.
Events
В этом пространстве имен собраны класы, описывающие базовую струкру евентов. Существует 2 типа классов: UnityAction (источник события) и UnityEvent (слушатель события, при этом есть возможность слушать несколько событий). Они могут принимать до 4-х параметров следующих типов: EventDefined, Void, Object, Int, Float, String, Bool (исходя из описания в Enum PresustentListenerMode).
EventSystems
Это пространство имен содержит в себе классы и интерфейсы, обеспечивающие обработку событий для элементов UI, при этом на каждое событие существует свой интерфейс. Также в этом пространстве имен находятся рейкастеры для физики и базовый класс для описания поведения UI элементов — UIBehaviour и настройки режимов ввода.
UI
Здесь находятся классы, непосредственно связанные с элементами UI. В том числе и описание для GraphicRaycaster, а также куча интерфейсов, связанных с событиями. Это пространство имен я еще только начал исследовать, именно там кроется ключ к написанию собственных элементов UI.
Следующую часть я напишу, когда разберусь, как все-таки создать собственные элементы управления. На этом всем спасибо, если у вас есть аналогичный опыт, буду рад прочитать о нем в комментариях.
Автор: nsavelev_unitydev