Canvas в Unity

Привіт! Нещодавно я думав про свій досвід роботи в якості Unity розробника і вирішив, що настав час поділитися тим, що я дізнався про створення інтерфейсів в Unity. Тож якщо це те, що ви шукали, читайте далі.

Повинен попередити, що ця серія статей не дасть вам вичерпного керівництва щодо роботи з HUD. Тут я просто хочу поділитися з вами своїми думками та спостереженнями. Але якщо ви хочете поділитися власним досвідом або найкращими практиками, будь ласка, зробіть це в розділі коментарів нижче.

Зміст

Ігрові інтерфейси

Що таке Canvas?

Режими відображення Canvas

Розміщення елементів у Canvas

Розробка для мобільних пристроїв

Створення кастомного селектора

Ігрові інтерфейси

Загалом, ігрові інтерфейси - це повнофункціональні окремі елементи, які безпосередньо не впливають на ігровий процес. Їхнє основне завдання - надати користувачам корисну інформацію про гру, яка може їм знадобитися. Технічно кажучи, ви можете взяти щось просте, наприклад, шрифт Arial, і використовувати його для відображення здоров'я, боєприпасів і рахунку (якщо ви робите шутер). Так, це зіпсує естетику (деякі особливо чутливі користувачі навіть скажуть, що їм потрібно звернутися до окуліста після того, як вони подивляться на вашу гру), але не можна сперечатися з тим, що вся необхідна інформація була там, голосно і чітко.

Але це досить радикальні методи. Звісно, найкращий інтерфейс - це той, який не нав'язливий і привертає увагу користувача лише тоді, коли він цього потребує. Показувати набої на зброї чи рівень здоров'я на головному герої (привіт, Dead Space!) - це рішення, які приймає геймдизайнер. Але ми, розробники ігор, існуємо для того, щоб реалізовувати всі незвичайні ідеї в реальних іграх. Тож які можливості для створення інтерфейсу є в Unity?

Що таке Canvas?

Канвас для Unity UI - це область, яка включає в себе всі елементи користувацького інтерфейсу. Отже, коли ми створюємо новий ігровий об'єкт, Canvas для нього створюється автоматично.

Починаючи з версії 4.6 для роботи з елементами інтерфейсу користувача використовується нова версія Unity UI. Елементи HUD (як і прості об'єкти) організовані в ієрархії з кореневим об'єктом, що містить Canvas. При цьому місце в ієрархії визначає порядок рендерингу: об'єкти, що знаходяться на найнижчому рівні, рендерингуються в останню чергу і, відповідно, розміщуються вище всіх інших.

Не має значення, який саме додаток ви розробляєте: як 3d, так і 2d ігри використовують однакову логіку при роботі з інтерфейсом. Те ж саме стосується і платформи. Неважливо, чи це веб з HTML5, чи гра для Android - достатньо буде описати лише один Canvas.

Режими відображення полотна

Режим рендерингу визначає, де відображатиметься полотно Unity UI Canvas (це може бути екран або світовий простір). Цей параметр має три різні режими:

  1. Екранний простір - Накладення - Полотно Полотно буде відрендерено поверх усіх елементів сцени. Якщо провести аналогію, то Canvas з елементами - це як вікно з наліпками в поїзді. Світ за вікном змінюється (камера рухається у Unity), але наліпки залишаються незмінними. Цей режим змінює полотно, коли змінюється розмір вікна. Він ідеально підходить для статичної інформації, такої як рахунок або елементи керування.
  2. Екранний простір - Камера - це те ж саме вікно, але замість стікерів воно має тривимірний колаж (неважливо, чи це 2D або 3D гра). Він також розміщується поверх усіх елементів сцени, але в цьому випадку елементи Полотна підпорядковуються законам перспективи (якщо тип проекції камери - Перспектива). Цей режим ідеально підходить для меню або інших елементів, які мають виглядати тривимірно.
  3. Світовий простір - режим, в якому Полотно є елементом сцени і може виступати як допоміжний елемент інших ігрових об'єктів. Цей режим ідеально підходить для мовних бульбашок персонажів, індикаторів набоїв для зброї тощо.

Розміщення елементів на полотні

Для цілей макетування кожен елемент інтерфейсу відображається у вигляді прямокутника. Два основних компоненти для роботи з ними - це Rect Tool та Rect Transform. Останній є новим компонентом, який має (поряд зі звичайними полями) спеціальне поле Anchors.

Rect Transform

Якорі визначають, як елементи прив'язуються до батьківського елемента. Компонент має 4 якоря, кожен з яких відповідає одній з вершин елемента. Позиція і розмір елемента обчислюється на основі відстані між вершиною і анкером та позиції анкера. Позиція якоря визначається у відсотках від батьківського елемента. Тому, коли всі чотири елементи розташовані в одному місці, розмір елемента є постійним. Якщо анкери, що належать до однієї площини (верхній і нижній або лівий і правий), розташовані в одній точці, елемент розтягується вздовж цієї осі. Якщо анкери, що належать до однієї площини, НЕ розташовані в одній точці, буде обчислено відсоткове положення кожного анкера і додано до відстані до вершини (вона не змінюється).

Звучить досить складно, чи не так? Але не бійтеся - витратьте 10 хвилин в редакторі і ви освоїте його тонкощі.

Створення кнопки в Unity

Варто також згадати, що окрім якорів Rect Transform також має параметри Min, Preferred та Flexible Width і Height, які ви можете перевизначити за допомогою компонента Layout Element (хоча особисто я його не використовую).

Layout Element (Script)

До речі, розробка Canvas для нової версії Unity UI має кілька цікавих особливостей. Одна з них - вимкнення всього інтерфейсу для спрощення роботи зі сценою. Для цього скористайтеся пунктом меню Layer у редакторі.

Вимкнення інтерфейсу

Перш за все здається, що Rect Transform надає достатньо функціональності і вам більше нічого не знадобиться. Але нещодавно під час написання кастомного селектора для Facebook мені знадобилося згрупувати елементи певним чином.

Під час написання селектора для Facebook мені знадобилося згрупувати елементи певним чином.

При розробці для мобільних пристроїв (якщо ви не працюєте виключно з iOS), людина стикається з проблемою сегментації пристроїв. Це означає, що його гра буде відкриватися на різних пристроях: 2'' або 9'' смартфонах або навіть планшетах. Що з цим робити? У нас є кілька варіантів.

Розробка для мобільних пристроїв

Чому не анкор?

Перше, що спадає на думку - це анкор. Так, це хороший варіант, якщо у вас прості екрани без великої кількості дочірніх елементів, анімації та інших привабливих для користувача елементів. Але при використанні цього типу макета слід пам'ятати, що змінюється розмір, а не візуальний масштаб елементів. Отже, компонент Best fit стає активним у текстових елементах, а також виникає необхідність контролювати співвідношення сторін і прив'язку до певних частин екрану або інших елементів. Це те, що спрацювало у мене (цей варіант не дуже елегантний, але він працює!).

У пакеті UI є компонент Aspect Ratio Fitter. Ось як він працює: залежно від типу та зміни розміру батьківського елемента цей компонент змінює розмір власного ігрового об'єкта, зберігаючи співвідношення сторін.

Aspect Ratio Fitter

До речі, є ще один компонент, Content Size Fitter, який працює навпаки: змінює розмір елемента залежно від його вмісту. Зазвичай він використовується з дочірніми ігровими об'єктами, що містять текстові компоненти, але також чудово працює з елементом Layout Element і групою Grid Layout.

Content Size Fitter

Переваги Canvas Scaler

Наразі я використовую Canvas Scaler, оскільки в цьому випадку компонент додається автоматично при створенні Canvas в інтерфейсі Unity UI. Основна перевага використання Canvas Scaler полягає в тому, що всі дочірні елементи масштабуються (а не просто змінюються їхні розміри). Таким чином, розмір шрифту в усіх текстах не змінюється, і всі елементи, зміщені на кілька одиниць, будуть виглядати однаково на всіх екранах.

Canvas Scaler може працювати в одному з трьох режимів:

  1. Константний розмір у пікселях - ігровий об'єкт зберігає свій розмір у пікселях незалежно від розміру екрана.
  2. Константний фізичний розмір - ігровий об'єкт зберігає свій фізичний розмір незалежно від розміру екрана та його співвідношення сторін.
  3. Масштабувати за розміром екрану - ігровий об'єкт масштабується разом з екраном.

Останній елемент є моїм улюбленим, оскільки він дозволяє забути про фрагментацію екрану. Ви просто обираєте цільову роздільну здатність і Canvas змінить його розмір оптимальним чином. Ось чому я хотів би, щоб ви подивилися на нього уважніше.

Canvas Scaler

Ви вже знаєте, що цей режим має власне цільове співвідношення сторін, яке режим узгодження екрана використовує для зміни поточного полотна. Режим узгодження може мати один з таких типів:

  1. Відповідність ширини або висоти - масштабує полотно залежно від співвідношення між шириною та/або висотою і фактичною шириною та висотою пристрою.
  2. Розширити - масштабує Полотно, включаючи ширшу сторону (Розмір Полотна ніколи не буде меншим за вказаний).
  3. Зменшити - масштабує полотно до меншої сторони (розмір полотна ніколи не буде більшим за вказаний).
.

І хоча кожен з режимів має свої переваги, Match Width Or Height все ж таки є моїм особистим фаворитом. Цей режим має ще одну корисну особливість: ви можете вказати, яку з осей буде використано як цільову, а яку - як опорну (всі полотна буде збільшено залежно від ширини, висоти або обох цих параметрів).

Це реалізовано за допомогою параметра Match, де для визначення співвідношення сторін використовується змінна float [0;1]. Якщо float = 0, зміни будуть зроблені відповідно до ширини, якщо float = 1 - відповідно до висоти. Коли цільове співвідношення сторін знаходиться в ландшафтному режимі, якщо Match = 0, ми отримаємо ефект розширення, якщо Match = 1 - звуження (в портретному режимі все навпаки: якщо Match = 0, ми отримаємо звуження, якщо Match = 1 - розширення).

Останній параметр Canvas Scaler - Reference Pixels per Unit - визначає, скільки пікселів міститься в одній одиниці елемента інтерфейсу. Його значення за замовчуванням дорівнює 100 метрів. Він працює з компонентами Image, тому якщо у вашій сцені кожен метр дорівнює 100 пікселям зображення і ви використовуєте фізику Unity, це значення є саме тим, що вам потрібно.

Створення користувацького селектора

Як я вже казав, у моєму випадку завдання полягало у написанні кастомного селектора для Facebook. Нам потрібен був динамічно згенерований список, з якого можна було б видаляти елементи на ходу. І хоча робота з Facebook API - це окрема тема, давайте закінчимо цей огляд нової версії Unity UI на макетах.

Layout

Як бачите, ми вже знайомі з деякими компонентами. Тож давайте ознайомимося з тими, про які ми ще нічого не знаємо.

Група полотен

Canvas Group

Цей компонент дуже простий у налаштуванні, але, тим не менш, дуже потужний. Він дозволяє керувати властивостями всіх дочірніх елементів об'єкта. Це корисно, коли нам потрібно зробити певну частину активною і заборонити їй реагувати на взаємодію користувача (через Raycast).

Для кращого розуміння створіть дві однакові панелі з кнопками та прапорцями. Додайте цей компонент на одну з них і спробуйте змінити значення параметрів.

І, нарешті, найцікавіше.

Горизонтальна група компонування та вертикальна група компонування

Horizontal Layout Group

Два компоненти розміщують усі дочірні компоненти по горизонталі та вертикалі один за одним. Для дочірніх елементів можна вказати як відступи, так і інтервали. Об'єкти також можна вказати відносно країв батьківського об'єкта.

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

GridLayoutGroup

Grid Layout Group

Якщо вам потрібно створити таблицю з однорідними елементами, це саме те, що вам потрібно! Він має відступи та інтервали (як і попередні елементи), але нам потрібно вказати розміри дочірнього елемента. Вони будуть використовуватися для зміни всіх об'єктів, які ми додамо до батьківського елемента.

Далі нам потрібно вказати StartCorner, який буде використано для визначення позиції першого елемента, і StartAxis, який буде використано для визначення осей заповнення (для рядків і стовпців). Якщо ви виберете Вертикальний, елементи будуть використовуватися для заповнення поточного стовпчика, доки не буде досягнуто краю батьківського елемента. Потім буде заповнено наступний стовпчик. У варіанті "Горизонтально" все навпаки: батьківський елемент заповнюється рядками. Після того, як ми визначили, де і як додавати елементи, логічно було б вказати їх вирівнювання.

Останній параметр - Обмеження. Він визначає, чи буде цей макет мати певну кількість стовпців і рядків, чи кількість стовпців і рядків буде розраховуватися на основі розміру батьківського елемента. Варто пам'ятати, що GroupLayout, на відміну від усіх інших компонентів компонування, заздалегідь визначає розмір дочірніх елементів за допомогою параметра Cell Size (йому байдуже до мінімального, бажаного та гнучкого розмірів).

Крім того, ви можете комбінувати GridLayoutGroup з ContantSizeFitter. Але для мене це було зайвим. Судячи з офіційної документації, це не повинно бути проблемою.

Ось кінцевий результат для мого випадку:

Використання кастомних селекторів

Кожен елемент було додано з автоматичною ініціалізацією з префабу. Як бачите, ми не можемо змінити розмір та позицію елемента, оскільки вони визначені у GridLayoutGroup.

Grid Layout Group

До речі, елемент був створений окремо від панелі, що було потрібно для його подальшого збереження. Усе, що мені потрібно було зробити, це скопіювати розмір елемента в компонент CellSize компонента GroupLayout. Щоб жорстко вказати розмір елемента, я вказав для CanvasScaler тип шкали Match Width або Height.

Це все про можливості нового інтерфейсу. Ця стаття є спробою систематизувати новий досвід, але якщо вона виявиться корисною для когось іншого, я буду більш ніж щасливий.

Щасливо і дякую за всю роботу.

Потрібна розробка MVP, додатків для iOS і Android або прототипування? Перегляньте наше портфоліо та зробіть замовлення вже сьогодні!