Нажми — и увидишь, что делает команда
- ⏱ Сколько займёт
- 30–50 минут, 5 шагов. Каждый шаг заканчивается результатом на экране.
- 💻 Что нужно
- Компьютер с Windows или macOS. Понадобится Unity — бесплатная для учёбы, поставим на первом шаге. С телефона этот квест не проходится.
- ⏸ Если прервёшься
- Ничего не потеряется: прогресс сохраняется на этом устройстве. Вернёшься — продолжишь с того же шага.
- 🎓 Чему научишься
- интерфейс Canvas · единый менеджер игры · сохранение рекорда
Игра начинает считать
На причале висит доска, и на ней мелом — чей улов больше. Половина доски стёрта.
«Мел смывает дождём, — Марк морщится. — А хороший счёт должен помнить рекорд, даже если ты ушёл спать».
Улов на экране, рекорд — в памяти. Так делают все игры, куда возвращаются на второй день.
Ролик 3D — он про то, как счёт и рекорд меняют игру. У тебя сцена 2D, и строчку «НОВЫЙ РЕКОРД!» ты добавишь сам, если захочешь: код рекорда для неё уже будет готов.
Читать текстом
Пока счёта нет, охота — просто движение. Со счётом она превращается в соревнование с самим собой.
Текст рисует пакет TextMeshPro. При первом добавлении Unity попросит импортировать ресурсы — соглашайся, это одна кнопка.
- 1ПКМ в Hierarchy → UI → Text - TextMeshProCanvas создастся сам — это отдельный слой поверх игры.
- 2Canvas Scaler в ИнспектореВыдели Canvas (не текст!): у него свой набор компонентов, схема на картинке — общая, для 2D-объекта. Найди Canvas Scaler, режим Scale With Screen Size, разрешение 1920×1080. Без этого на телефоне текст будет с ноготок.
- 3Квадратик привязокВыдели текст. Самый верхний компонент у него — Rect Transform, а слева в нём квадратик с крестиком: нажми его, зажми Alt и выбери левый верхний угол.
- 4Проверь в окне SceneТекст должен держаться угла, даже когда меняешь размер окна Game.
Стандартный шрифт Unity 6 обычно рисует и русские буквы. Но если вместо «Улов» ты увидишь квадратики — значит, нужных букв в шрифте нет: скачай бесплатный с fonts.google.com, положи в проект и сделай ему Font Asset (ПКМ → Create → TextMeshPro → Font Asset), затем поставь его тексту в поле Font Asset.
Одна копилка на всю игру
using UnityEngine; using TMPro; public class GameManager : MonoBehaviour { public static GameManager Instance; // единственный экземпляр [SerializeField] private TMP_Text scoreText; private int score = 0; private void Awake() { Instance = this; // «я тут главный» } public void AddScore(int amount) { score += amount; scoreText.text = $"Улов: {score}"; } }
static значит «поле принадлежит не объекту, а всему классу» — до него можно дотянуться откуда угодно. Приём называется синглтон: один-единственный менеджер на всю игру. Если проходил Godot: это близкий родственник автозагрузки.Значок $ перед строкой позволяет вставлять переменные прямо в текст в фигурных скобках. Удобнее, чем склеивать плюсами.
private void OnTriggerEnter2D(Collider2D other) { if (other.CompareTag("Fish")) { GameManager.Instance.AddScore(1); // зовём метод менеджера Destroy(other.gameObject); } }
Создай пустой объект GameManager на сцене (ПКМ в Hierarchy → Create Empty), повесь на него скрипт и перетащи в поле Score Text объект с текстом.
Частая ошибка: тащат сам Canvas. Нужен объект внутри него — строка Text (TMP). Поле принимает только его, потому что тип поля — TMP_Text.

- 1Hierarchy — Canvas и Text (TMP)ПКМ по пустому месту → UI → Text - TextMeshPro. Canvas и EventSystem создадутся сами: Canvas — это отдельный слой поверх игры.
- 2Rect Transform — рамка надписиУ интерфейса вместо обычного Transform вот такой. Pos X и Pos Y — где висит, Width и Height — размер рамки. Здесь 200 на 50.
- 3Квадратик привязокНажми на него и с зажатым Alt выбери левый верхний угол. Тогда счёт прилипнет к углу и не уедет ни на широком экране, ни на телефоне.
- 4Text Input — что написано на экранеБольшое поле в компоненте TextMeshPro; сейчас в нём SCORE: 120. Сюда же код пишет строку «Улов: 7». Русские буквы станут квадратиками, пока не подключишь свой шрифт.
- 5Game — так это видит игрокНадпись видна в левом нижнем углу. Поменяй размер окна Game: счёт должен держаться угла. Уехал — вернись к квадратику привязок.
Это настоящий экран Unity 6 — такой же, как у тебя. Нажимай на кружки по порядку: метка покажет место, строка ниже объяснит, зачем оно. Отмечай пройденное — прогресс сохранится.
Рекорд, который переживёт выход
[SerializeField] private TMP_Text bestText; // второй текст на Canvas private int best = 0; private void Start() { best = PlayerPrefs.GetInt("BestScore", 0); // 0 — если рекорда ещё нет bestText.text = $"Рекорд: {best}"; } public void AddScore(int amount) { score += amount; scoreText.text = $"Улов: {score}"; if (score > best) { best = score; PlayerPrefs.SetInt("BestScore", best); // записали на диск bestText.text = $"Рекорд: {best}"; } }
PlayerPrefs — маленькое хранилище прямо на компьютере игрока. Числа, строки, галочки. Для рекорда, громкости и последнего уровня — самое то. Для больших сохранений берут файлы.Теперь рекорд не пропадёт после выхода из игры. Проверь: набери счёт, закрой Play, запусти снова.
if (Keyboard.current.rKey.wasPressedThisFrame)
PlayerPrefs.DeleteKey("BestScore");
Метода Update() в менеджере ещё нет — допиши его. И вверху файла добавь строку using UnityEngine.InputSystem;, иначе Keyboard не найдётся. Только не забудь убрать сброс из готовой игры — иначе игроки найдут.

Рекорд — причина вернуться завтра
Аркады семидесятых заканчивались таблицей рекордов с тремя буквами имени. Ради этих трёх букв люди приходили в зал снова.
Сегодня приём тот же: сохранённый рекорд превращает случайную игру в соревнование с собой вчерашним.
Важная мелочь: рекорд должен пережить закрытие игры. Всё, что стирается при выходе, игрок не воспринимает всерьёз.
Разная добыча — разная цена
using UnityEngine; public class Fish : MonoBehaviour { [SerializeField] private int cost = 1; // сколько стоит эта рыба public int Cost => cost; // отдаём наружу только чтение }
=> — короткая запись «просто верни это значение». Такое свойство можно читать, но нельзя менять снаружи. Мелкой рыбе поставь 1, крупной 3, золотой 10.А в пасти вместо жёсткой единицы возьми цену у самой рыбы:
if (other.CompareTag("Fish")) { int cost = 1; if (other.TryGetComponent(out Fish fish)) cost = fish.Cost; GameManager.Instance.AddScore(cost); Destroy(other.gameObject); }
TryGetComponent — «попробуй найти такую деталь; получилось — положи её в переменную». Безопаснее обычного GetComponent: если детали нет, игра не сломается, а спокойно пойдёт дальше.Экран, который читается
Последний пункт — приём из настоящей разработки. Он называется плейтест, и заменить его ничем нельзя.
Читать текстом
Задание студии: сделай таймер на 60 секунд. Когда время выйдет, охота заканчивается и показывается итог. Подсказка: в Update отнимай Time.deltaTime от переменной timeLeft.
Поднимай флаг.