Урок 6 из 8 · 25 мин · обновлено
Интерфейс: счёт, жизни и кнопки
Как устроены Canvas и элементы интерфейса в Unity, как вывести счёт текстом TextMeshPro, привязать элементы к краям экрана и связать скрипты между собой через менеджер игры.
Canvas: холст интерфейса
Счёт, жизни, кнопки и меню в Unity рисуются на Canvas — холсте поверх игры. Создайте текст: в Hierarchy правая кнопка → UI → Text - TextMeshPro. Unity сама создаст Canvas и поместит текст внутрь. Если появится окно импорта ресурсов TextMeshPro, нажмите Import TMP Essentials.
Сразу настройте у Canvas компонент Canvas Scaler: режим Scale With Screen Size и эталонное разрешение 1920 × 1080. Тогда интерфейс будет пропорционально увеличиваться и уменьшаться на разных экранах.
Создайте два текста: ScoreText и LivesText.
Якоря
Положение элемента интерфейса задаётся в компоненте Rect Transform, а отсчитывается от якорей (Anchors). Нажмите на квадрат в левом верхнем углу Rect Transform и выберите вариант «левый верхний угол». Удерживайте Alt, чтобы элемент сразу туда переехал.
Теперь счёт всегда в левом верхнем углу: и на ноутбуке, и на широком мониторе, и на телефоне.
Русский текст. Стандартный шрифт TextMeshPro не содержит кириллицы, и вместо русских букв появятся квадраты. Добавьте в проект шрифт с кириллицей, например бесплатный Roboto или PT Sans. Нажмите на файл шрифта правой кнопкой → Create → TextMeshPro → Font Asset и выберите получившийся ассет в поле Font Asset у текстов.
GameManager: менеджер игры
Пока счёт хранится в игроке. Но о монетах должен знать и интерфейс, а позже — экран победы. Удобнее держать состояние игры в одном месте. Создайте пустой объект (Create Empty), назовите GameManager и повесьте на него скрипт:
using TMPro;
using UnityEngine;
public class GameManager : MonoBehaviour
{
[SerializeField] private TMP_Text scoreText;
[SerializeField] private TMP_Text livesText;
[SerializeField] private int coinsToWin = 5;
private int coins;
private int lives = 3;
void Start()
{
UpdateUI();
}
public void AddCoin()
{
coins++;
UpdateUI();
}
public void LoseLife()
{
lives--;
UpdateUI();
}
private void UpdateUI()
{
scoreText.text = $"Монеты: {coins} из {coinsToWin}";
livesText.text = $"Жизни: {lives}";
}
}
TMP_Text— тип текста TextMeshPro, для него подключаемusing TMPro;;$"Монеты: {coins} из {coinsToWin}"— строка с подстановкой: значения переменных встают на место фигурных скобок;- методы
AddCoinиLoseLifeпубличные (public): их будут вызывать другие скрипты.
Перетащите ScoreText и LivesText из Hierarchy в одноимённые поля GameManager в Inspector.
Игрок сообщает менеджеру
В PlayerController уберите свои счётчики coins и lives и добавьте ссылку на менеджер:
[SerializeField] private GameManager gameManager;
void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Coin"))
{
Destroy(other.gameObject);
gameManager.AddCoin();
}
}
void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.CompareTag("Hazard"))
{
gameManager.LoseLife();
}
}
Перетащите объект GameManager в поле Game Manager у игрока. Нажмите Play: счёт и жизни меняются на экране.
Кнопки работают так же: UI → Button - TextMeshPro, а в Inspector в событии On Click нажмите плюс, перетащите объект со скриптом и выберите публичный метод. Кнопки понадобятся в следующем уроке для перезапуска игры.
Попробуйте сами. Добавьте таймер: на уровень даётся 60 секунд, в правом верхнем углу видно «Время: 42». Когда время вышло, выведите в Console «Время вышло».
Решение
Создайте текст TimerText, привяжите его якорем к правому верхнему углу. В GameManager добавьте:
[SerializeField] private TMP_Text timerText;
[SerializeField] private float timeLeft = 60f;
private bool timeOver;
void Update()
{
if (timeOver)
{
return;
}
timeLeft -= Time.deltaTime;
timerText.text = $"Время: {Mathf.CeilToInt(timeLeft)}";
if (timeLeft <= 0)
{
timeOver = true;
Debug.Log("Время вышло");
}
}
Time.deltaTime каждый кадр вычитает прошедшие секунды. Mathf.CeilToInt округляет вверх, чтобы на экране было «1», пока не прошла последняя секунда. Флаг timeOver не даёт сообщению повторяться каждый кадр.
Мини-тест: проверьте себя
Закрепите урок: несколько вопросов, разбор ответов — в конце.
-
Где должны находиться текст счёта и кнопки, чтобы Unity нарисовала их поверх игры?
Canvas — холст интерфейса. Всё, что внутри него, рисуется поверх игрового мира и подстраивается под размер экрана.
-
Счёт в левом верхнем углу на широком мониторе уехал в середину экрана. Что настроено неправильно?
Якоря задают, от какой точки экрана отсчитывается положение элемента. Привязанный к углу текст остаётся в углу при любом разрешении.
-
Зачем выносить подсчёт монет и жизней в отдельный скрипт GameManager?
Когда счёт, жизни, победа и интерфейс собраны в одном менеджере, их проще менять. Игрок только сообщает: «подобрал монету» или «ударился».
-
Что нужно, чтобы кнопка могла вызвать метод Restart() из скрипта?
В событии On Click кнопки указывают объект и его публичный метод. Приватные методы в этом списке не показываются.