Shape Match!
Ещё неделю назад закончил небольшую игрушку, но написать решил только сейчас.
Простая головоломка с комбинированием фигурок. Ваша задача - очистить поле. Выбор трёх одинаковых фигурок подряд удаляет их, а заполнение всех ячеек ведёт к проигрышу.
При разработке помимо стандартного функционала Unity использовался DOTween для анимаций интерфейса и YG Plugin для интеграции с Yandex Games.
Подробнее изучить архитектуру проекта можно вот тут:
https://github.com/RedAtomTeam/ShapeMatch
Поиграть вот здесь:
https://yandex.com/games/app/442255?lang=ru
Ещё неделю назад закончил небольшую игрушку, но написать решил только сейчас.
Простая головоломка с комбинированием фигурок. Ваша задача - очистить поле. Выбор трёх одинаковых фигурок подряд удаляет их, а заполнение всех ячеек ведёт к проигрышу.
При разработке помимо стандартного функционала Unity использовался DOTween для анимаций интерфейса и YG Plugin для интеграции с Yandex Games.
Подробнее изучить архитектуру проекта можно вот тут:
https://github.com/RedAtomTeam/ShapeMatch
Поиграть вот здесь:
https://yandex.com/games/app/442255?lang=ru
🎨 UI в Unity: Часть 1 – Canvas в Unity
Графический интерфейс в Unity строится на трёх китах: Canvas, Raycaster и Canvas Scaler. Давайте разберём, как они работают вместе!
🖼 Canvas — холст для UI
Что делает?
1. Контейнер для всех UI-элементов (кнопки, тексты, изображения)
2. Определяет пространство рендеринга:
2.1. Screen Space (поверх камеры)
2.2. World Space (как 3D-объект в сцене)
2.3. Camera Space (привязан к камере)
🎯 Graphic Raycaster — обработка кликов
Зачем нужен?
1. Отвечает за взаимодействие с UI (клики, наведение)
2. Работает только с объектами внутри Canvas
Совет:
1. Для World Space UI добавьте Physics Raycaster на камеру – он нужен для обработки кликов в мировом пространстве.
📏 Canvas Scaler — контроль масштаба
Решает проблему: Как UI должен выглядеть на разных разрешениях?
Режимы масштабирования:
1. Constant Pixel Size — UI всегда одного размера в пикселях(Десктоп-приложения)
2. Scale With Screen Size — Масштабируется относительно разрешения(Мобильные игры)
3. Constant Physical Size — Сохраняет размер в реальных единицах (мм/дюймах)(AR/VR)
Настройки для Scale With Screen Size:
Reference Resolution (например, 1920x1080)
Match (Width/Height) — что в приоритете
🔗 Как они связаны?
Canvas рендерит UI-элементы
Canvas Scaler адаптирует их под разные экраны
Graphic Raycaster обрабатывает ввод (клики, тачи)
💡 Практические советы
Для мобильных игр используйте:
Scale Mode: Scale With Screen Size
Screen Match Mode: Expand (чтобы UI не обрезался)
Оптимизация:
Объединяйте элементы в одном Canvas (меньше draw calls)
Отключайте Raycaster для статичных UI
World Space UI:
Настройте Event Camera в Graphic Raycaster
Добавьте Physics Raycaster на основную камеру
⚠️ Частые ошибки
1. UI не кликается → Проверьте:
1.1. Наличие Graphic Raycaster
1.2. Блокирующие прозрачные объекты
1.3. Order in Layer
2. Размытый текст → Выберите правильный Render Mode в Canvas
3. UI "уплывает" → Для World Space настройте Rect Transform
Графический интерфейс в Unity строится на трёх китах: Canvas, Raycaster и Canvas Scaler. Давайте разберём, как они работают вместе!
🖼 Canvas — холст для UI
Что делает?
1. Контейнер для всех UI-элементов (кнопки, тексты, изображения)
2. Определяет пространство рендеринга:
2.1. Screen Space (поверх камеры)
2.2. World Space (как 3D-объект в сцене)
2.3. Camera Space (привязан к камере)
🎯 Graphic Raycaster — обработка кликов
Зачем нужен?
1. Отвечает за взаимодействие с UI (клики, наведение)
2. Работает только с объектами внутри Canvas
Совет:
1. Для World Space UI добавьте Physics Raycaster на камеру – он нужен для обработки кликов в мировом пространстве.
📏 Canvas Scaler — контроль масштаба
Решает проблему: Как UI должен выглядеть на разных разрешениях?
Режимы масштабирования:
1. Constant Pixel Size — UI всегда одного размера в пикселях(Десктоп-приложения)
2. Scale With Screen Size — Масштабируется относительно разрешения(Мобильные игры)
3. Constant Physical Size — Сохраняет размер в реальных единицах (мм/дюймах)(AR/VR)
Настройки для Scale With Screen Size:
Reference Resolution (например, 1920x1080)
Match (Width/Height) — что в приоритете
🔗 Как они связаны?
Canvas рендерит UI-элементы
Canvas Scaler адаптирует их под разные экраны
Graphic Raycaster обрабатывает ввод (клики, тачи)
💡 Практические советы
Для мобильных игр используйте:
Scale Mode: Scale With Screen Size
Screen Match Mode: Expand (чтобы UI не обрезался)
Оптимизация:
Объединяйте элементы в одном Canvas (меньше draw calls)
Отключайте Raycaster для статичных UI
World Space UI:
Настройте Event Camera в Graphic Raycaster
Добавьте Physics Raycaster на основную камеру
⚠️ Частые ошибки
1. UI не кликается → Проверьте:
1.1. Наличие Graphic Raycaster
1.2. Блокирующие прозрачные объекты
1.3. Order in Layer
2. Размытый текст → Выберите правильный Render Mode в Canvas
3. UI "уплывает" → Для World Space настройте Rect Transform
🛠 UI в Unity: Часть 2 – Пассивные UI-элементы
Пассивные элементы — это UI-компоненты, которые не взаимодействуют с пользователем напрямую, но критично важны для организации интерфейса.
🔍 Основные элементы:
1. Image (Raw Image)
1.1. Простое отображение спрайтов/текстур
1.2. Используется для:
1.2.1. Фонов
1.2.2. Иконок без клика
1.2.3. Декоративных элементов
2. Text (TextMeshPro)
2.1. Вывод статичного текста (подписи, описания)
2.2. Важно: Для динамического текста лучше использовать TextMeshPro
3. Mask
3.1. Обрезает дочерние элементы по заданной области
3.2. Пример: скролл-списки с видимой областью
4. Layout Group
4.1. Автоматически упорядочивает дочерние объекты:
4.1.1. Horizontal/Vertical – линейное расположение
4.1.2. Grid – сетка
4.1.3. Content Size Fitter – подстраивает размер под контент
5. Panel
5.1. Группирует другие элементы (обычно с Image-фоном)
💡 Зачем нужны?
Организация – структурируют интерфейс
Оптимизация – уменьшают количество draw calls при группировке
Гибкость – работают в связке с активными элементами (кнопками, полями ввода)
⚠️ Ошибки новичков:
Использование Image вместо Raw Image для динамических текстур
Отсутствие Layout Group при ручном позиционировании однотипных элементов
Пассивные элементы — это UI-компоненты, которые не взаимодействуют с пользователем напрямую, но критично важны для организации интерфейса.
🔍 Основные элементы:
1. Image (Raw Image)
1.1. Простое отображение спрайтов/текстур
1.2. Используется для:
1.2.1. Фонов
1.2.2. Иконок без клика
1.2.3. Декоративных элементов
2. Text (TextMeshPro)
2.1. Вывод статичного текста (подписи, описания)
2.2. Важно: Для динамического текста лучше использовать TextMeshPro
3. Mask
3.1. Обрезает дочерние элементы по заданной области
3.2. Пример: скролл-списки с видимой областью
4. Layout Group
4.1. Автоматически упорядочивает дочерние объекты:
4.1.1. Horizontal/Vertical – линейное расположение
4.1.2. Grid – сетка
4.1.3. Content Size Fitter – подстраивает размер под контент
5. Panel
5.1. Группирует другие элементы (обычно с Image-фоном)
💡 Зачем нужны?
Организация – структурируют интерфейс
Оптимизация – уменьшают количество draw calls при группировке
Гибкость – работают в связке с активными элементами (кнопками, полями ввода)
⚠️ Ошибки новичков:
Использование Image вместо Raw Image для динамических текстур
Отсутствие Layout Group при ручном позиционировании однотипных элементов
🥰1
🎬 UI в Unity: Часть 3 – Видео
Хотите добавить видеоролики в свою игру?
Разберём все ключевые моменты — от форматов до практической реализации.
📹 Поддерживаемые форматы
Unity работает с этими видеоформатами:
- MP4 (H.264 + AAC) — рекомендуемый
- MOV (только для macOS/iOS)
- WebM (для WebGL)
⚠️ Важно:
- Видео должно быть перекодировано под платформу (например, через HandBrake)
- Разрешение желательно кратное 4 (например, 1920×1080)
🛠 3 способа вывода видео
1. VideoPlayer + RenderTexture (универсальный)
Как настроить:
- Импортируйте видеофайл в проект
- Создайте RenderTexture (Assets → Create → Render Texture)
- Добавьте компонент VideoPlayer на объект:
- Назначьте RenderTexture на материал объекта
Плюсы:
- Работает на всех платформах
- Можно проецировать на 3D-объекты
2. VideoPlayer + RawImage (для UI)
Настройка:
- Создайте Canvas и добавьте RawImage
- Настройте VideoPlayer:
Идеально для:
- Заставок
- Видеофонов меню
3. Прямой вывод на камеру
Настройка:
Особенности:
- Видео заменяет фон камеры
- Подходит для AR/VR
⚠️ Частые проблемы
1. Чёрный экран → Проверьте:
- Назначен ли RenderTexture
- Поддерживается ли кодек на целевой платформе
2. Нет звука → Добавьте AudioSource и настройте вывод аудио
3. Тормозит на мобилках → Уменьшите разрешение видео (720p вместо 4K)
Хотите добавить видеоролики в свою игру?
Разберём все ключевые моменты — от форматов до практической реализации.
📹 Поддерживаемые форматы
Unity работает с этими видеоформатами:
- MP4 (H.264 + AAC) — рекомендуемый
- MOV (только для macOS/iOS)
- WebM (для WebGL)
⚠️ Важно:
- Видео должно быть перекодировано под платформу (например, через HandBrake)
- Разрешение желательно кратное 4 (например, 1920×1080)
🛠 3 способа вывода видео
1. VideoPlayer + RenderTexture (универсальный)
Как настроить:
- Импортируйте видеофайл в проект
- Создайте RenderTexture (Assets → Create → Render Texture)
- Добавьте компонент VideoPlayer на объект:
VideoPlayer vp = gameObject.AddComponent<VideoPlayer>();
vp.renderMode = VideoRenderMode.RenderTexture;
vp.targetTexture = myRenderTexture; // Ваша RenderTexture
vp.Play();
- Назначьте RenderTexture на материал объекта
Плюсы:
- Работает на всех платформах
- Можно проецировать на 3D-объекты
2. VideoPlayer + RawImage (для UI)
Настройка:
- Создайте Canvas и добавьте RawImage
- Настройте VideoPlayer:
VideoPlayer vp = gameObject.AddComponent<VideoPlayer>();
vp.renderMode = VideoRenderMode.MaterialOverride;
vp.targetMaterialRenderer = GetComponent<Renderer>();
vp.Play();
Идеально для:
- Заставок
- Видеофонов меню
3. Прямой вывод на камеру
Настройка:
VideoPlayer vp = cameraGO.AddComponent<VideoPlayer>();
vp.renderMode = VideoRenderMode.CameraFarPlane;
vp.Play();
Особенности:
- Видео заменяет фон камеры
- Подходит для AR/VR
⚠️ Частые проблемы
1. Чёрный экран → Проверьте:
- Назначен ли RenderTexture
- Поддерживается ли кодек на целевой платформе
2. Нет звука → Добавьте AudioSource и настройте вывод аудио
3. Тормозит на мобилках → Уменьшите разрешение видео (720p вместо 4K)
🎮 UI в Unity: Часть 4 – EventSystem или как работает взаимодействие с UI?
EventSystem — это "мозг" обработки ввода в Unity UI. Без него ваши кнопки не будут кликаться! Разберём его работу в 5 ключевых пунктах.
🔧 Что делает EventSystem?
1. Обрабатывает клики/тапы через StandaloneInputModule (ПК/мобилки)
2. Передаёт события всем UI-элементам
3. Управляет фокусом (например, для клавиатурного ввода)
🛠 Основные компоненты
Input Module — Преобразует ввод (мышь/тач/геймпад) в события
Raycaster — Определяет, по какому объекту кликнули
EventSystem — Координирует работу всей системы
Важно:
На сцене должен быть ровно один EventSystem
Для World Space UI нужен Physics Raycaster
💡 Как настроить?
1. Автоматически:
При создании UI через GameObject → UI → Button Unity добавляет:
- EventSystem
- StandaloneInputModule
- GraphicRaycaster
2. Вручную:
⚠️ Частые проблемы
1. Кнопки не работают → Проверьте:
- Наличие EventSystem на сцене
- Не перекрывают ли другие объекты UI
- Не отключён ли Raycaster
2. Не работает тач на мобилках → Замените StandaloneInputModule на TouchInputModule
3. World Space UI не кликается → Добавьте PhysicsRaycaster на камеру
EventSystem — это "мозг" обработки ввода в Unity UI. Без него ваши кнопки не будут кликаться! Разберём его работу в 5 ключевых пунктах.
🔧 Что делает EventSystem?
1. Обрабатывает клики/тапы через StandaloneInputModule (ПК/мобилки)
2. Передаёт события всем UI-элементам
3. Управляет фокусом (например, для клавиатурного ввода)
🛠 Основные компоненты
Input Module — Преобразует ввод (мышь/тач/геймпад) в события
Raycaster — Определяет, по какому объекту кликнули
EventSystem — Координирует работу всей системы
Важно:
На сцене должен быть ровно один EventSystem
Для World Space UI нужен Physics Raycaster
💡 Как настроить?
1. Автоматически:
При создании UI через GameObject → UI → Button Unity добавляет:
- EventSystem
- StandaloneInputModule
- GraphicRaycaster
2. Вручную:
// Добавить кастомный ввод (например, для геймпада)
var es = gameObject.AddComponent<EventSystem>();
es.AddComponent<StandaloneInputModule>();
⚠️ Частые проблемы
1. Кнопки не работают → Проверьте:
- Наличие EventSystem на сцене
- Не перекрывают ли другие объекты UI
- Не отключён ли Raycaster
2. Не работает тач на мобилках → Замените StandaloneInputModule на TouchInputModule
3. World Space UI не кликается → Добавьте PhysicsRaycaster на камеру
🎮 UI в Unity: Часть 5 – Активные UI-элементы
Активные элементы — это "живые" компоненты интерфейса, которые реагируют на действия пользователя. Давайте разберём ключевые из них!
🕹 Основные активные элементы
1. Кнопка (Button)
- Зачем: Основной элемент для кликов/тапов
- Фишки:
- 4 состояния (Normal, Highlighted, Pressed, Disabled)
- Событие onClick для привязки действий
2. Поле ввода (InputField/TMP_InputField)
- Зачем: Текстовый ввод (логины, чаты)
- Фишки:
- Валидация (цифры/буквы/пароли)
- События onValueChanged, onEndEdit
3. Переключатель (Toggle)
- Зачем: Чекбоксы и радио-кнопки
- Фишки:
- Группировка через Toggle Group
- Событие onValueChanged
4. Слайдер (Slider)
- Зачем: Выбор значений в диапазоне (громкость, настройки)
- Фишки:
- Настройка min/max значений
- Событие onValueChanged
5. Скроллвью (ScrollView)
- Зачем: Прокрутка контента (списки, инвентарь)
- Фишки:
- Вертикальный/горизонтальный режим
- Оптимизация через Mask + Layout Group
⚡️ Важные особенности
- Наследование от Selectable – все активные элементы имеют:
- Состояния (Hover, Pressed)
- Навигацию (клавиши/геймпад)
- Требуют EventSystem – без него не будут работать!
💡 Советы по использованию
1. Для текста всегда выбирайте TextMeshPro (лучше качество)
2. Оптимизация: Отключайте ненужные Raycast Target у декоративных элементов
3. Анимации: Добавляйте эффекты через Animator к состояниям (например, пульсацию при наведении)
Активные элементы — это "живые" компоненты интерфейса, которые реагируют на действия пользователя. Давайте разберём ключевые из них!
🕹 Основные активные элементы
1. Кнопка (Button)
- Зачем: Основной элемент для кликов/тапов
- Фишки:
- 4 состояния (Normal, Highlighted, Pressed, Disabled)
- Событие onClick для привязки действий
// Пример скрипта для кнопки
button.onClick.AddListener(() => Debug.Log("Клик!"));
2. Поле ввода (InputField/TMP_InputField)
- Зачем: Текстовый ввод (логины, чаты)
- Фишки:
- Валидация (цифры/буквы/пароли)
- События onValueChanged, onEndEdit
inputField.onEndEdit.AddListener(text => Debug.Log($"Введено: {text}"));3. Переключатель (Toggle)
- Зачем: Чекбоксы и радио-кнопки
- Фишки:
- Группировка через Toggle Group
- Событие onValueChanged
toggle.onValueChanged.AddListener(isOn => Debug.Log($"Состояние: {isOn}"));4. Слайдер (Slider)
- Зачем: Выбор значений в диапазоне (громкость, настройки)
- Фишки:
- Настройка min/max значений
- Событие onValueChanged
slider.onValueChanged.AddListener(value => audio.volume = value);
5. Скроллвью (ScrollView)
- Зачем: Прокрутка контента (списки, инвентарь)
- Фишки:
- Вертикальный/горизонтальный режим
- Оптимизация через Mask + Layout Group
⚡️ Важные особенности
- Наследование от Selectable – все активные элементы имеют:
- Состояния (Hover, Pressed)
- Навигацию (клавиши/геймпад)
- Требуют EventSystem – без него не будут работать!
💡 Советы по использованию
1. Для текста всегда выбирайте TextMeshPro (лучше качество)
2. Оптимизация: Отключайте ненужные Raycast Target у декоративных элементов
3. Анимации: Добавляйте эффекты через Animator к состояниям (например, пульсацию при наведении)
Как вы могли заметить, я немного пропал и совсем ничего не постил — исправляюсь! Сейчас готовлю материалы по нескольким темам: профайлинг, новая система инпута, Scriptable Objects и Character Controller. По итогам я хочу показать вам применение всего, что мы до этого изучали на конкретном примере. Есть несколько идей и я предложу вам выбрать после того, как мы рассмотрим все нужные темы. А пока выбирайте, с чего вы хотели бы начать?
С чего начнём?
Anonymous Poll
20%
Профайлинг
20%
Новая система инпута
40%
Scriptable Objects
20%
Character Controller
Чтож, промежуточный результат голосования я вижу - думаю, что в дальнейшем он не изменится, а потому приступаю к написанию постов по Scriptable Objects. Чтобы материал не был сухим и оторванным от реальности я покажу работу SO на примере небольшого глоссария — раздела игры, посвящённого разным врагам. Заодно коснёмся темы UI. Ждите совсем скоро - будет интересно!
🎮 ScriptableObjects в Unity
ScriptableObject (SO) — это мощный инструмент для хранения данных и логики вне GameObject.
Идеально для: настроек персонажей, информации о предметах, диалогов и любых конфигов!
🔥 Зачем использовать?
✔️ Экономия памяти – один SO может использоваться тысячами объектов
✔️ Гибкость – изменение данных без правки кода
✔️ Интеграция с Inspector – настройки как у компонентов
🛠 Основы создания
Скрипт:
Для создания ScriptableObject важно наследовать класс от ScriptableObject и использовать модификатор [CreateAssetMenu], указав название для создаваемых SO и положение объекта во всплывающем меню.
Создание ассета:
ПКМ в Project → Create → Characters → CharacterData
Заполните параметры в инспекторе
💡 Пример: Базовая система персонажей
1. Данные персонажа (SO)
2. Использование в скрипте
3. Преимущества подхода
- Можно создать разные вариации персонажей (игрок, враг, NPC) без дублирования кода - достаточно установить новый конфиг для изменения настроек персонажа.
- Баланс игры меняется без пересборки – просто редактируем SO
- Данные можно переиспользовать (например, несколько врагов с одними параметрами)
📊 Когда выбирать ScriptableObject?
1. Настройки персонажей/врагов — ✅ Идеально
2. Система диалогов/квестов — ✅ Отлично
Используя эти знания можно создавать множество конфигов с разными предустановками, чтобы в дальнейшем легко менять настройки объекта установив подходящий конфиг. Так же, это позволяет управлять настройками множества объектов, имеющих один и тот же конфиг - например, если у вас есть множество врагов одного типа и все они имеют один и тот же конфиг, то для изменения их поведения достаточно изменить данные установленного конфига.
Вдальнейшем мы напишем небольшой глоссарий, описывающий информацию о различных противниках. Ждите – следующий пост совсем скоро!
ScriptableObject (SO) — это мощный инструмент для хранения данных и логики вне GameObject.
Идеально для: настроек персонажей, информации о предметах, диалогов и любых конфигов!
🔥 Зачем использовать?
✔️ Экономия памяти – один SO может использоваться тысячами объектов
✔️ Гибкость – изменение данных без правки кода
✔️ Интеграция с Inspector – настройки как у компонентов
🛠 Основы создания
Скрипт:
using UnityEngine;
[CreateAssetMenu(fileName = "NewCharacter", menuName = "Characters/CharacterData")]
public class CharacterData : ScriptableObject {
public string characterName;
public int maxHealth;
public float moveSpeed;
}
Для создания ScriptableObject важно наследовать класс от ScriptableObject и использовать модификатор [CreateAssetMenu], указав название для создаваемых SO и положение объекта во всплывающем меню.
Создание ассета:
ПКМ в Project → Create → Characters → CharacterData
Заполните параметры в инспекторе
💡 Пример: Базовая система персонажей
1. Данные персонажа (SO)
using UnityEngine;
[CreateAssetMenu(fileName = "NewCharacter", menuName = "Characters/CharacterData")]
public class CharacterData : ScriptableObject {
public string characterName;
public int maxHealth;
public float moveSpeed;
}
2. Использование в скрипте
// PlayerController.cs
public class PlayerController : MonoBehaviour {
public CharacterData data; // Перетащите сюда SO
private int currentHealth;
void Start() {
currentHealth = data.maxHealth;
}
void Update() {
float move = Input.GetAxis("Horizontal") * data.moveSpeed;
transform.Translate(move * Time.deltaTime, 0, 0);
}
}
3. Преимущества подхода
- Можно создать разные вариации персонажей (игрок, враг, NPC) без дублирования кода - достаточно установить новый конфиг для изменения настроек персонажа.
- Баланс игры меняется без пересборки – просто редактируем SO
- Данные можно переиспользовать (например, несколько врагов с одними параметрами)
📊 Когда выбирать ScriptableObject?
1. Настройки персонажей/врагов — ✅ Идеально
2. Система диалогов/квестов — ✅ Отлично
Используя эти знания можно создавать множество конфигов с разными предустановками, чтобы в дальнейшем легко менять настройки объекта установив подходящий конфиг. Так же, это позволяет управлять настройками множества объектов, имеющих один и тот же конфиг - например, если у вас есть множество врагов одного типа и все они имеют один и тот же конфиг, то для изменения их поведения достаточно изменить данные установленного конфига.
Вдальнейшем мы напишем небольшой глоссарий, описывающий информацию о различных противниках. Ждите – следующий пост совсем скоро!
ScriptableObjects: Создание глоссария - часть 1
📊Проектирование
Для создания глоссария мы будем использовать ScriptableObjects, который будут хранить информацию о каждом типе противников.
Для создания класса нам необходимо выделить наиболее важные и общие для всех врагов параметры. В моём случае это будут:
1. Название типа противников
2. Здоровье противников
3. Урон противников.
При желании можно расширить перечень параметров, если вы решите использовать в игре более сложные системы противников. Например, вы можете добавить скорость в виде float-поля по аналогии с тем, как я реализую остальные поля.
🛠Создание конфигов
Чтобы создать ScriptableObject вам необходимо создать базовый скрипт в файлах проекта: ПКМ -> Create -> C# Script.
После этого переименуйте скрипт в соответствии с тем, что вы создаёте. В моём случае скрипт называется Enemy.
Открыв скрипт, измените код программы следующим образом:
Изначально в вашем скрипте может быть больше строк using, но используется в данном случае лишь одна, поэтому остальные были удалены за ненадобностью.
Вместо наследования от MonoBehaviour наш класс наследуется от ScriptableObject. Также перед объявлением класса мы используем CreateAssetMenu, чтобы обозначить изначальное название конфига при создании и то, где мы сможем найти его во всплывающем меню. Исходя из приведённого выше кода мы сможем создать Enemy используя ПКМ -> Create -> Entities -> Enemy
✍🏻Итог
Таким образом мы можем создавать множество различных объектов Enemy, представляющих данные о противниках. Я создал три объекта Enemy - попробуйте создать ещё трёх своих.
В следующем посте сверстаем UI для глоссария – ждите совсем скоро!
📊Проектирование
Для создания глоссария мы будем использовать ScriptableObjects, который будут хранить информацию о каждом типе противников.
Для создания класса нам необходимо выделить наиболее важные и общие для всех врагов параметры. В моём случае это будут:
1. Название типа противников
2. Здоровье противников
3. Урон противников.
При желании можно расширить перечень параметров, если вы решите использовать в игре более сложные системы противников. Например, вы можете добавить скорость в виде float-поля по аналогии с тем, как я реализую остальные поля.
🛠Создание конфигов
Чтобы создать ScriptableObject вам необходимо создать базовый скрипт в файлах проекта: ПКМ -> Create -> C# Script.
После этого переименуйте скрипт в соответствии с тем, что вы создаёте. В моём случае скрипт называется Enemy.
Открыв скрипт, измените код программы следующим образом:
using UnityEngine;
[CreateAssetMenu(fileName = "Enemy", menuName = "Entities/Enemy")]
public class Enemy : ScriptableObject
{
public string enemyName;
public int hp;
public int damage;
}
Изначально в вашем скрипте может быть больше строк using, но используется в данном случае лишь одна, поэтому остальные были удалены за ненадобностью.
Вместо наследования от MonoBehaviour наш класс наследуется от ScriptableObject. Также перед объявлением класса мы используем CreateAssetMenu, чтобы обозначить изначальное название конфига при создании и то, где мы сможем найти его во всплывающем меню. Исходя из приведённого выше кода мы сможем создать Enemy используя ПКМ -> Create -> Entities -> Enemy
✍🏻Итог
Таким образом мы можем создавать множество различных объектов Enemy, представляющих данные о противниках. Я создал три объекта Enemy - попробуйте создать ещё трёх своих.
В следующем посте сверстаем UI для глоссария – ждите совсем скоро!
This media is not supported in your browser
VIEW IN TELEGRAM
ScriptableObjects: Создание глоссария - часть 2
В этом посте мы наконец разберём вёрстку глоссария, иными словами реализация макета, на котором будет выводиться информация о наших противниках.
🛠Подготовка
Для начала нужно настроить холст. Нам понадобится лишь установить Scale With Screen Size, чтобы объекты Canvas масштабировались вместе с изменением размеров экрана, после чего нужно выставить эталонное разрешение - то, которое установлено у вас во вкладке Game. У меня, как вы видите, это 1920х1080.
Далее требуется разбить глоссарий на нижнюю и верхнюю область. Обратите внимание, что это сделано с использованием так называемых “якорей”(Anchors). Если говорить по простому, то якорь, это точка, к которой привинчивается объект на макете(Canvas). Это может быть середина холста, его нижний левый край или произвольная, выбранная вами точка. Также каждый якорь может быть прикручен к разным точкам, и тогда вместо указания позиции для объекта мы будем указывать отступы от якорей. Использование якорей это навык очень важный для вёрстки. Тема использования якорей достаточно важна, поэтому её нельзя игнорировать, но также эта тема не настолько велика, чтобы писать отдельный пост. Накидайте бананов, если хотите подробно разобрать позиционирование UI элементов на Canvas
❓Что нужно отображать?
После того, как мы установили базовый макет, нужно определиться с тем, что мы будем выводить на этом макете? В случае с нашими ScriptableObject`ами – это имя, здоровье и урон, то есть те самые параметры, которые мы определили для них в прошлом посте.
Чтобы выводить эту информацию нам понадобится объект с компонентом TextMeshPro – этот элемент вы сможете найти во вкладке UI во всплывающем окошке при попытке создать объект. Я создаю пары Label-Value, то есть объект, указывающий на тип значения и само значение, чтобы пользователь по подписи мог понять, что является здоровьем, а что уроном. Затем нужно лишь расставить эти элементы на холсте
🧐Кого нужно отображать?
Создав макет и добавив поля для вывода информации нам остаётся лишь добавить интерфейс для выбора противников, информацию о которых пользователь сможет узнать. Для этого в нижней части экрана я создаю кнопки – объекты Button, подписывая их так, чтобы пользователь понимал, какого противника он выберет для рассмотрения при нажатии.
✍🏻Итог
Теперь у нас есть набор конфигов, каждый из которых хранит информацию о конкретном противнике и макет глоссария, через который пользователь сможет рассмотреть информацию о каждом из противников. В следующем посте мы наконец добавим скрипты для управления этим макетом и установления связи между ним и конфигами, чем, наконец, закроем тему ScriptableObject. Ждите совсем скоро!
В этом посте мы наконец разберём вёрстку глоссария, иными словами реализация макета, на котором будет выводиться информация о наших противниках.
🛠Подготовка
Для начала нужно настроить холст. Нам понадобится лишь установить Scale With Screen Size, чтобы объекты Canvas масштабировались вместе с изменением размеров экрана, после чего нужно выставить эталонное разрешение - то, которое установлено у вас во вкладке Game. У меня, как вы видите, это 1920х1080.
Далее требуется разбить глоссарий на нижнюю и верхнюю область. Обратите внимание, что это сделано с использованием так называемых “якорей”(Anchors). Если говорить по простому, то якорь, это точка, к которой привинчивается объект на макете(Canvas). Это может быть середина холста, его нижний левый край или произвольная, выбранная вами точка. Также каждый якорь может быть прикручен к разным точкам, и тогда вместо указания позиции для объекта мы будем указывать отступы от якорей. Использование якорей это навык очень важный для вёрстки. Тема использования якорей достаточно важна, поэтому её нельзя игнорировать, но также эта тема не настолько велика, чтобы писать отдельный пост. Накидайте бананов, если хотите подробно разобрать позиционирование UI элементов на Canvas
❓Что нужно отображать?
После того, как мы установили базовый макет, нужно определиться с тем, что мы будем выводить на этом макете? В случае с нашими ScriptableObject`ами – это имя, здоровье и урон, то есть те самые параметры, которые мы определили для них в прошлом посте.
Чтобы выводить эту информацию нам понадобится объект с компонентом TextMeshPro – этот элемент вы сможете найти во вкладке UI во всплывающем окошке при попытке создать объект. Я создаю пары Label-Value, то есть объект, указывающий на тип значения и само значение, чтобы пользователь по подписи мог понять, что является здоровьем, а что уроном. Затем нужно лишь расставить эти элементы на холсте
🧐Кого нужно отображать?
Создав макет и добавив поля для вывода информации нам остаётся лишь добавить интерфейс для выбора противников, информацию о которых пользователь сможет узнать. Для этого в нижней части экрана я создаю кнопки – объекты Button, подписывая их так, чтобы пользователь понимал, какого противника он выберет для рассмотрения при нажатии.
✍🏻Итог
Теперь у нас есть набор конфигов, каждый из которых хранит информацию о конкретном противнике и макет глоссария, через который пользователь сможет рассмотреть информацию о каждом из противников. В следующем посте мы наконец добавим скрипты для управления этим макетом и установления связи между ним и конфигами, чем, наконец, закроем тему ScriptableObject. Ждите совсем скоро!
Media is too big
VIEW IN TELEGRAM
Пока готовится следующий пост по глоссарию решил поделиться с вами актуальным проектом. Вдохновился "ULTRAKILL" и решил создать свой FPS. Систему движений решил скопировать, а графику планирую сделать похожей на "Buckshot roulette". Пока тестирую физику, подбираю визуал и интерфейс. Как вам?
This media is not supported in your browser
VIEW IN TELEGRAM
ScriptableObjects: Создание глоссария - часть 3
Это завершающий пост цикла и в нём мы рассмотрим создание управляющего скрипта, который будет управлять отображением нужной информации.
🛠Проектирование
Прежде чем приступать к написанию скрипта, нужно определиться с задачами, которые он должен решать. Какого функционала мы ожидаем от нашего глоссария? Для такой системы можно придумать множество дополнительных фич, таких как: звуковой эффект при выборе, подсветка выбранной кнопки, изменение её размера, анимации и так далее. В нашем случае мы обойдёмся самым простым вариантом - изменение содержимого текстовых полей при нажатии на кнопки. Для этого будет достаточно одного скрипта, который будет содержать ссылки на нужные текстовые поля и публичный метод для вывода информации о враге. Давайте перейдём к реализации скрипта
🧑💻Код
Это весь код, необходимый для работы нашего глоссария. Мы используем обычный MonoBehaviour, в котором определяем три приватных поля. Благодаря модификатору [SerializeField] мы сможем указать ссылки через инспектор несмотря на приватность. Именно эти поля будет менять скрипт внутри своего публичного метода ShowEnemyInfo(). Как видно из кода, метод принимает один аргумент как раз того типа, который мы создавали в первом посте для хранения конфигов о противнике. Теперь всё готово и осталось добавить скрипт на сцену
⚙️Настройка
Скрипт можно установить на любой объект в сцене, главное это установить в нём ссылки на нужные текстовые объекты, которые и будут отображать соответствующие значения. После этого остаётся лишь добавить на каждую кнопку событие, в которое мы установим ссылку на объект с нашим скриптом и вызовем созданный нами метод, передав ему тот конфиг врага, который должна представлять кнопка.
✍🏻Итог
Теперь у нас есть полностью рабочая система глоссария, отображающая информацию о любом враге, которого мы выберем. Для масштабирования подобной системы достаточно лишь создать ещё больше конфигов и добавить больше кнопок!
Это завершающий пост цикла и в нём мы рассмотрим создание управляющего скрипта, который будет управлять отображением нужной информации.
🛠Проектирование
Прежде чем приступать к написанию скрипта, нужно определиться с задачами, которые он должен решать. Какого функционала мы ожидаем от нашего глоссария? Для такой системы можно придумать множество дополнительных фич, таких как: звуковой эффект при выборе, подсветка выбранной кнопки, изменение её размера, анимации и так далее. В нашем случае мы обойдёмся самым простым вариантом - изменение содержимого текстовых полей при нажатии на кнопки. Для этого будет достаточно одного скрипта, который будет содержать ссылки на нужные текстовые поля и публичный метод для вывода информации о враге. Давайте перейдём к реализации скрипта
🧑💻Код
using TMPro;
using UnityEngine;
public class GlossaryInfoShowController : MonoBehaviour
{
[SerializeField] private TextMeshProUGUI _enemyName;
[SerializeField] private TextMeshProUGUI _hp;
[SerializeField] private TextMeshProUGUI _damage;
public void ShowEnemyInfo(Enemy enemyConfig)
{
_enemyName.text = enemyConfig.enemyName;
_hp.text = enemyConfig.hp.ToString();
_damage.text = enemyConfig.damage.ToString();
}
}
Это весь код, необходимый для работы нашего глоссария. Мы используем обычный MonoBehaviour, в котором определяем три приватных поля. Благодаря модификатору [SerializeField] мы сможем указать ссылки через инспектор несмотря на приватность. Именно эти поля будет менять скрипт внутри своего публичного метода ShowEnemyInfo(). Как видно из кода, метод принимает один аргумент как раз того типа, который мы создавали в первом посте для хранения конфигов о противнике. Теперь всё готово и осталось добавить скрипт на сцену
⚙️Настройка
Скрипт можно установить на любой объект в сцене, главное это установить в нём ссылки на нужные текстовые объекты, которые и будут отображать соответствующие значения. После этого остаётся лишь добавить на каждую кнопку событие, в которое мы установим ссылку на объект с нашим скриптом и вызовем созданный нами метод, передав ему тот конфиг врага, который должна представлять кнопка.
✍🏻Итог
Теперь у нас есть полностью рабочая система глоссария, отображающая информацию о любом враге, которого мы выберем. Для масштабирования подобной системы достаточно лишь создать ещё больше конфигов и добавить больше кнопок!
Та самая моделька оружия, которая используется в моём FPS. Уже делаю ещё 3 модельки
🔥4🌭1