К карте
ВЕРФЬ · UNITY · КВЕСТ 6
Три укуса
0
Прогресс0 / 5
СДЕЛАЙ ПЕРВЫЙ ХОД

Нажми — и увидишь, что делает команда

Жми кнопки по очереди — это три настоящие команды.
ПЕРЕД СТАРТОМ
⏱ Сколько займёт
30–50 минут, 5 шагов. Каждый шаг заканчивается результатом на экране.
💻 Что нужно
Компьютер с Windows или macOS. Понадобится Unity — бесплатная для учёбы, поставим на первом шаге. С телефона этот квест не проходится.
⏸ Если прервёшься
Ничего не потеряется: прогресс сохраняется на этом устройстве. Вернёшься — продолжишь с того же шага.
🎓 Чему научишься
здоровье и урон · экран проигрыша · первая сборка игры
ШАГ 1 ИЗ 5 · ВЕРФЬ · UNITY · КВЕСТ 6

Здоровье и цена ошибки

ЧТО ПРОИСХОДИТ
ЭПИЗОД 6Глубина за банкой

Первый укус — испуг. Второй — кровь в воде. Третьего может не быть.

«Три укуса, — Марк показывает три пальца. — Больше не выдержит никто. И это честно: игрок должен видеть, сколько у него осталось».

А когда всё кончится — покажи экран проигрыша и дай кнопку «ещё раз». Без неё игру закрывают навсегда.

Марк · корабельный мастер верфи
ЧТО ПОЛУЧИТСЯ
ЗАПИСЬ ГОТОВОЙ ИГРЫ
Три полоски внизу — это здоровье. Каждый укус гасит одну, после удара — полсекунды неуязвимости. Когда полосок не осталось — экран проигрыша.

Ролик 3D — он про ощущение: три жизни, укус, конец. Твоя «Глубина» останется 2D, но здоровье, урон, экран проигрыша и кнопка «ещё раз» будут ровно те же.

СНАЧАЛА — ПОСМОТРИ
ЖИВАЯ ЗАПИСЬ ДВИЖКА
Враг кусает, здоровье падает, при нуле — конец. Игра научилась заканчиваться.
Марк
Читать текстом
Сборщик, у твоей игры пока нет цены ошибки: врезался во врага — и ничего не случилось. Сегодня появятся здоровье, урон и экран проигрыша с кнопкой «ещё раз». Секрет честности такой: после укуса игроку дают полсекунды неуязвимости. Без неё здоровье утекает за одно касание, и игру закрывают навсегда. А в самом конце квеста ты соберёшь билд — готовый файл, который запускается без Unity.

Экран «Игра окончена» — тоже часть игры, и делать его надо всерьёз.

ЗАДАНИЕ 1 · ЗДОРОВЬЕ
PlayerHP.csC#
using UnityEngine;
using TMPro;

public class PlayerHP : MonoBehaviour
{
    [SerializeField] private TMP_Text hpText;
    [SerializeField] private int HP = 3;      // три укуса — и всё

    private void Start() => hpText.text = $"{HP}";

    public void Damage(int damage)      // публичный — его позовёт враг
    {
        HP -= damage;
        if (HP < 0) HP = 0;             // не уходим в минус
        hpText.text = $"{HP}";

        if (HP == 0)
            GameManager.Instance.GameOver();
    }
}
Ключевое слово public здесь важно: метод должен быть виден чужому скрипту. Всё остальное в классе оставляем закрытым.

Это первый твой метод, который зовут снаружи. До сих пор все функции Unity вызывал сам.

ШАГ 2 ИЗ 5 · ВЕРФЬ · UNITY · КВЕСТ 6

Укус

ЗАДАНИЕ 2 · УКУС
EnemyMouth.csC#
using UnityEngine;

public class EnemyMouth : MonoBehaviour
{
    [SerializeField] private int biteDamage = 1;   // один укус — одна полоска

    private void OnTriggerEnter2D(Collider2D other)
    {
        if (other.CompareTag("Player"))
        {
            if (other.TryGetComponent(out PlayerHP playerHP))
            {
                playerHP.Damage(biteDamage);   // зовём чужой метод
            }
        }
    }
}
Вот он, момент, ради которого метод сделали публичным. Пасть врага не лезет к чужим переменным — она просит объект сделать с собой то, что тот умеет. Это главное правило больших проектов.

Врагу нужен свой Mouth — дочерний объект с маленьким триггером спереди. Тот же приём, что был у акулы игрока.

Почему враг зовёт playerHP.Damage(1), а не пишет playerHP.HP -= 1 напрямую?
Так меньше кода
Метод сам следит за правилами: не уходит в минус, обновляет текст, проверяет конец игры
Прямое обращение к полям в C# запрещено
НЕПРОБИВАЕМЫЕ ПОЛСЕКУНДЫ
Проверь: заплыви прямо во врага и постой. Здоровье будет утекать при каждом касании — играть невозможно. В настоящих играх после урона дают полсекунды неуязвимости. Заведи флаг и корутину прямо в PlayerHP.cs (вверху файла добавь using System.Collections;):

private bool canBeHit = true;

public void Damage(int damage)
{
    if (!canBeHit) return;  // ещё неуязвим
    StartCoroutine(Invuln());
    // ...дальше прежний код: HP -= damage и остальное
}

private IEnumerator Invuln()
{
    canBeHit = false;
    yield return new WaitForSeconds(0.5f);
    canBeHit = true;
}
НАСТОЯЩИЙ ЭКРАН UNITY — КУДА НАЖИМАТЬ
ТВОЙ ЭКРАН UNITY — КУДА НАЖИМАТЬнажми на кружок — покажу место
Окно редактора
  • 1Hierarchy — дай врагу пастьПКМ по врагу → Create Empty, назови Mouth. Маленький коллайдер с галочкой Is Trigger спереди — это и есть зубы.
  • 2Tag Player — на акулеСкрипт EnemyMouth проверяет CompareTag("Player"). Забыл тег — укусов не будет, и полчаса уйдёт на поиск ошибки в коде, которой там нет.
  • 3Куда вешать скриптыPlayerHP — на акулу, EnemyMouth — на объект Mouth врага, Flash — туда же, где Sprite Renderer. Кнопка Add Component ждёт в самом низу Инспектора.
  • 4Play — дай себя укуситьПроверяй всё разом: цифра здоровья падает, акула коротко краснеет, на нуле появляется панель «Игра окончена» и время замирает.
  • 5Game — и отсюда же собирают билдИгра должна читаться и в маленьком окне. Сборка живёт в меню File → Build Profiles: строка меню идёт по самому верху экрана, выше окна Unity, — на кадр она не попала.
Отмечено:0 из 5

Это настоящий экран Unity 6 — такой же, как у тебя. Нажимай на кружки по порядку: метка покажет место, строка ниже объяснит, зачем оно. Отмечай пройденное — прогресс сохранится.

ШАГ 3 ИЗ 5 · ВЕРФЬ · UNITY · КВЕСТ 6

Экран проигрыша

ЗАДАНИЕ 3 · ПАНЕЛЬ
GameManager.csC#
using UnityEngine;
using UnityEngine.SceneManagement;

public class GameManager : MonoBehaviour
{
    // ДОБАВЬ это в свой GameManager из квеста 4.
    // Instance, scoreText, best и AddScore остаются на месте!
    [SerializeField] private GameObject gameOverPanel;

    public void GameOver()
    {
        gameOverPanel.SetActive(true);   // показали панель
        Time.timeScale = 0f;             // остановили время
    }

    public void Restart()
    {
        Time.timeScale = 1f;             // время обратно!
        SceneManager.LoadScene(SceneManager.GetActiveScene().name);
    }
}
Time.timeScale = 0 замораживает игру целиком: движение, физику, анимации. Так делают паузу почти во всех проектах. Главное — не забыть вернуть единицу, иначе после перезапуска игра останется стоять и ты будешь долго искать причину.

Собери панель: Panel на Canvas, внутри крупный текст «Игра окончена», итоговый счёт и кнопка. Изначально выключи её галочкой сверху Инспектора.

Файл не переписывай. Открой свой GameManager.cs из четвёртого квеста и допиши в него поле gameOverPanel и два метода, а строку using UnityEngine.SceneManagement; добавь к тем using, что уже есть. Заменишь файл целиком — потеряешь счёт и рекорд, а GameManager.Instance перестанет компилироваться.

ЗАДАНИЕ 4 · КНОПКА
1
Кнопка «Заново»
UI → Button - TextMeshPro. Положи на панель.
2
Привяжи действие
Выдели кнопку. В самом низу Инспектора, в компоненте Button, есть блок On Click () — жми +. В пустой строке слева перетащи объект GameManager из Hierarchy, потом в списке справа (он станет активным) выбери GameManager → Restart (). Список серый — значит объект слева не положен.
3
Проверь
Дай себя укусить до нуля. Панель появится, время остановится, кнопка перезапустит уровень.
4
Покажи счёт на панели
Игроку важно узнать результат — это то, ради чего он захочет сыграть ещё раз.
Ты забыл вернуть Time.timeScale = 1 в методе Restart. Что произойдёт?
Сцена перезагрузится, но всё в ней будет неподвижно
Игра вылетит
Ничего, timeScale сбрасывается сам
ЭКСКУРС
КАК В НАСТОЯЩИХ ИГРАХ

Почему жизней всегда мало

Три сердца, три жизни, три попытки — это не случайность. Три достаточно, чтобы ошибиться и исправиться, но мало, чтобы расслабиться.

Ещё игры дают невидимую поблажку: после удара герой примерно полсекунды неуязвим. Без неё враг забирает всё здоровье за одно касание, и игру бросают.

И главное — кнопка «ещё раз». Игра, где после проигрыша нужно что-то искать в меню, теряет половину игроков на первой смерти.

ШАГ 4 ИЗ 5 · ВЕРФЬ · UNITY · КВЕСТ 6

Обратная связь: что со мной было

ЗАДАНИЕ 5 · ВСПЫШКА
Flash.csC#
using System.Collections;
using UnityEngine;

public class Flash : MonoBehaviour
{
    [SerializeField] private Color hitColor = Color.red;
    private SpriteRenderer sr;
    private Color normal;

    private void Start()
    {
        sr = GetComponent<SpriteRenderer>();
        normal = sr.color;
    }

    public IEnumerator Blink()
    {
        sr.color = hitColor;
        yield return new WaitForSeconds(0.12f);
        sr.color = normal;
    }
}
Повесь Flash на объект Player — рядом с PlayerHP. Затем в PlayerHP.cs добавь поле private Flash flash;, в Start() строку flash = GetComponent<Flash>(); — и вызывай StartCoroutine(flash.Blink()); из метода Damage. Двенадцать сотых секунды — на глаз это короткая вспышка, и её достаточно, чтобы игрок понял: «меня задело».

Без такой мелочи игрок теряет здоровье и не понимает, за что. Красная вспышка стоит десять строк, а меняет ощущение полностью.

ЧИСЛА, КОТОРЫЕ РАБОТАЮТ
0,12 с
вспышка при уроне
0,5 с
неуязвимость после укуса
3
укуса до конца игры — обычный баланс аркады

Эти числа не выведены формулой — их подобрали руками тысячи разработчиков. Начни с них и подстрой под себя.

ШАГ 5 ИЗ 5 · ВЕРФЬ · UNITY · КВЕСТ 6

Первый билд

ЗАДАНИЕ 6 · ФИНАЛЬНОЕ
СБОРКА ИГРЫ — ЖМИ НА КРУЖОКнажми на кружок — покажу место
FileEditAssetsGameObjectComponentWindowHelpLayout⬡ HierarchySampleSceneMain CameraDirectional LightPlayerBackgroundWaterSurface◈ SceneGame⚙ InspectorPlayerTransformSprite RendererRigidbody 2DBox Collider 2DAdd Component▤ ProjectConsoleAssetsScenesScriptsSprites▶ Game
  • 1File → Build ProfilesОткроется отдельное окно поверх редактора — кружки на этой схеме показывают порядок действий, а не место на экране. Слева в столбце Platforms выбери Windows или macOS, ту, на которой работаешь, и нажми Switch Platform, если она не активна.
  • 2Add Open ScenesКнопка в окне сборки. Забудешь — в билд не попадёт ни одна сцена, и запустится чёрный экран.
  • 3Выбери пустую папку и жми BuildUnity соберёт готовую программу. Это займёт несколько минут.
  • 4Запусти файл — игра работает без UnityЕё можно скинуть другу, положить на флешку или выложить в интернет.
Отмечено:0 из 4

Это тот самый момент, ради которого шла экспедиция «Глубина». Программа, которую написал ты, теперь запускается сама — без Unity и без тебя.

НОРА · ВЕДУЩАЯ СТУДИИ
Экспедиция «Глубина» закрыта. Твоя игра умеет считать, ранить, заканчиваться и перезапускаться — и, главное, существует отдельным файлом, который можно отдать другому человеку.
Марк
Читать текстом
Экспедиция «Глубина» закрыта. Игра умеет считать, ранить, заканчиваться и начинаться заново. А главное — теперь она существует отдельным файлом, который можно скинуть другу на флешку или выложить в интернет. Это и называется сборкой, ради неё всё затевалось. Дальше море закончится: пойдём на берег лепить землю кистями и ставить свет.

Задание студии: собери версию под WebGL и выложи её на itch.io. Игра откроется прямо в браузере по ссылке — той, которой можно поделиться с кем угодно.

Заложи на это вечер, а не полчаса: сначала в Unity Hub придётся доставить модуль WebGL Build Support (около гигабайта), сама сборка идёт 10–20 минут, а для itch.io нужен аккаунт — заводи его вместе с родителем.

Поднимай флаг.

Экспедиция закрыта!

Урон, проигрыш, перезапуск и собственный билд игры готовы. Грейд МИДЛ-РАЗРАБОТЧИК.

Что дальше. Верфь осталась за спиной. Марк ведёт по тропе вверх, к старым дозорным вышкам.

🏅 Забрать диплом Следующий квест: Берег дозорных Следующая экспедиция: третье измерение
🔒

Этот остров ещё закрыт

Сначала пройди предыдущий квест — хотя бы просмотри все шаги.

⚑ Экспедиционный режим