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

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

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

В глубине живёт кто-то ещё

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

За песчаной банкой вода темнеет. Оттуда всплывает пузырь размером с голову.

«Ты был самым крупным ровно один день, — Марк не улыбается. — Там, внизу, есть крупнее».

Он не видит дальше своего носа. Но если ты войдёшь в его круг — пойдёт следом и не отстанет.

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

Ролик 3D и вид сверху — он показывает саму идею зоны зрения. У тебя будет 2D: круглый триггер вокруг врага и погоня, когда игрок в него вошёл. Надпись «ЗАМЕЧЕН» — необязательный бонус: заведи TMP-текст и включай его там же, где заполняется Target.

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

Сегодня появится первый противник, который принимает решения.

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

И собирать мы его будем из отдельных маленьких скриптов, а не одного большого. Один отвечает за поворот, другой за глаза, третий за движение. Так проще чинить и переделывать.

ТРИ ДЕТАЛИ ВРАГА
EnemyRotation.cs
куда смотреть
Случайно меняет курс, пока никого не видит.
EnemyEyes.cs
кого вижу
Триггер-круг: запоминает игрока, когда тот входит, и забывает при выходе.
EnemyMovement.cs
куда плыть
Если цель есть — к ней. Если нет — вперёд по своему курсу.

Это называется компонентный подход: поведение раскладывают по деталям и собирают врагов как конструктор. Если проходил Godot: там ты бы написал один скрипт на узел — здесь привычнее иначе.

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

Глаза

ЗАДАНИЕ 1 · ЗРЕНИЕ
EnemyEyes.csC#
using UnityEngine;

public class EnemyEyes : MonoBehaviour
{
    public GameObject Target { get; private set; }   // читать всем, менять — только тут

    private void OnTriggerEnter2D(Collider2D other)
    {
        if (other.CompareTag("Player"))
            Target = other.gameObject;
    }

    private void OnTriggerExit2D(Collider2D other)
    {
        if (other.CompareTag("Player"))
            Target = null;                            // уплыл — забыли
    }
}
{ get; private set; } — свойство, которое снаружи можно только читать. OnTriggerExit2D — событие выхода из зоны. Именно оно даёт врагу «терять» игрока.

Сделай врагу дочерний объект Eyes с большим CircleCollider2D и галочкой Is Trigger. Радиус этого круга — и есть дальность зрения.

Сначала — тег игрока. Выдели Player в Hierarchy → вверху Инспектора Tag → Player (такой тег в Unity уже есть, создавать не надо). Без него CompareTag("Player") никогда не сработает, а Console промолчит — самый обидный вид ошибки.

Что случится, если убрать OnTriggerExit2D?
Враг перестанет видеть игрока
Враг запомнит игрока навсегда и будет гнаться через всю карту
Ничего не изменится
НАСТОЯЩИЙ ЭКРАН UNITY — КУДА НАЖИМАТЬ
ТВОЙ ЭКРАН UNITY — КУДА НАЖИМАТЬнажми на кружок — покажу место
Окно редактора
  • 1Hierarchy — собери врага целикомCreate Empty → назови Enemy. Внутри него ещё два пустых объекта: Eyes (большой круг зрения) и Mouth (маленький круг пасти).
  • 2Tag — поставь акуле PlayerГлаза врага узнают героя только по тегу. Строка Tag — в самом верху Инспектора. Не поставил — враг смотрит сквозь тебя.
  • 3Три скрипта врага — три Add ComponentEnemyEyes на объект Eyes, EnemyMovement и EnemyRotation на самого врага. Потом перетащи Eyes в поле eyes у скрипта движения. Add Component — в самом низу этого списка.
  • 4Project — перетащи врага сюдаПолучится префаб. Расставь хоть десять врагов: поправишь заготовку — изменятся сразу все.
  • 5Play — проверь, где он тебя замечаетПодплывай медленно. Пока не видит — плывёт по своим делам, увидел — разгоняется. Окно Game внизу слева.
Отмечено:0 из 5

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

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

Погоня

ЗАДАНИЕ 2 · ПРЕСЛЕДОВАНИЕ
EnemyMovement.csC#
using UnityEngine;

public class EnemyMovement : MonoBehaviour
{
    [SerializeField] private float speed = 1.5f;
    [SerializeField] private float chaseSpeed = 3f;
    [SerializeField] private EnemyEyes eyes;

    private Rigidbody2D body;

    private void Awake() => body = GetComponent<Rigidbody2D>();

    private void FixedUpdate()
    {
        if (eyes.Target != null)
        {
            Vector2 dir = (eyes.Target.transform.position - transform.position).normalized;
            transform.right = dir;
            body.linearVelocity = dir * chaseSpeed;
        }
        else
        {
            body.linearVelocity = transform.right * speed;
        }
    }
}
FixedUpdate вызывается с ровным шагом — для физики он правильнее, чем Update. Вычитание позиций даёт вектор «отсюда туда»; .normalized убирает из него длину, оставляя только направление.

Заметь: враг в погоне быстрее, чем на прогулке. Так игрок чувствует момент, когда его заметили.

НАЙДИ ОШИБКУ
EnemyMovement.csнажми на строку с ошибкой
1private void FixedUpdate()
2{
3 if (eyes.Target != null)
4 {
5 Vector2 dir = eyes.Target.transform.position - transform.position;
6 body.linearVelocity = dir * chaseSpeed;
7 }
8}
Издалека враг несётся с бешеной скоростью, а вблизи почти стоит.

Враг ведёт себя странно: заметив игрока с другого конца карты, разгоняется до неприличия, а подплыв вплотную — почти останавливается. Найди строку.

ЭКСКУРС
КАК В НАСТОЯЩИХ ИГРАХ

Зона зрения: как враг «замечает»

Враг в игре не видит по-настоящему. Обычно вокруг него просто круг: вошёл в круг — значит замечен.

В играх про скрытность круг превращают в конус — как луч фонаря. Отсюда весь стелс: обойди сзади, и ты невидим.

Хорошие игры честно показывают момент обнаружения: знак над головой, звук, смена музыки. Иначе игрок считает, что его убили несправедливо.

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

Свой курс, когда никого нет

ЗАДАНИЕ 3 · ПАТРУЛЬ
EnemyRotation.csC#
using UnityEngine;

public class EnemyRotation : MonoBehaviour
{
    [SerializeField] private float rotateTime = 2f;
    [SerializeField] private EnemyEyes eyes;

    private float timer = 0f;
    private SpriteRenderer sr;

    private void Start() => sr = GetComponent<SpriteRenderer>();

    private void Update()
    {
        if (eyes.Target == null)          // курс меняем, только когда никого не видим
        {
            timer -= Time.deltaTime;
            if (timer <= 0f)
            {
                Vector3 look = Random.insideUnitCircle;
                look.z = 0f;
                transform.right = look;
                timer = rotateTime;
            }
        }

        sr.flipY = transform.right.x < 0f;   // анти-кувырок
    }
}
Ссылку на SpriteRenderer берут один раз в Start, а не каждый кадр: GetComponent в Update — классическая причина тормозов, когда врагов становится много. И обрати внимание на последнюю строку: курс меняем только без цели, а flipY считаем всегда — иначе в погоне враг поплывёт кверху брюхом.
Почему GetComponent вызывают в Start, а не каждый кадр в Update?
В Update он не работает
Это поиск детали на объекте — делать его 60 раз в секунду для каждого врага расточительно
Так требует C#
ШАГ 5 ИЗ 5 · ВЕРФЬ · UNITY · КВЕСТ 5

Настрой опасность

ЗАДАНИЕ 4 · ФИНАЛЬНОЕ
СБОРКА ВРАГА — ЖМИ НА КРУЖОКнажми на кружок — покажу место
FileEditAssetsGameObjectComponentWindowHelpLayout⬡ HierarchySampleSceneMain CameraDirectional LightPlayerBackgroundWaterSurface◈ SceneGame⚙ InspectorPlayerTransformSprite RendererRigidbody 2DBox Collider 2DAdd Component▤ ProjectConsoleAssetsScenesScriptsSprites▶ Game
  • 1Собери врага целиком в HierarchyСпрайт, Rigidbody 2D (обязательно Gravity Scale = 0, как у игрока, иначе враг утонет при Play), коллайдер и два дочерних объекта: Eyes и Mouth.
  • 2Три скрипта — три Add ComponentEnemyRotation, EnemyEyes, EnemyMovement. Каждый отвечает за своё: куда смотреть, кого вижу, куда плыть.
  • 3Поля скриптов в ИнспектореВыдели врага: у компонентов Enemy Movement и Enemy Rotation есть поле Eyes. Перетащи в него строку Eyes из Hierarchy — дочерний объект самого врага. Пустое поле — враг не увидит игрока, а Console выдаст NullReferenceException.
  • 4Перетащи врага в окно ProjectПолучится префаб. Теперь одного врага можно расставить хоть десять раз, и правка заготовки поменяет всех.
  • 5Поставь двух-трёх на картуНе больше: в маленьком море четыре хищника — это уже давка, а не игра.
Отмечено:0 из 5

Радиус зрения и разница скоростей — два числа, которые решают, будет игра честной или несправедливой.

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

Задание студии: сделай, чтобы враг терял интерес не сразу. Пусть после выхода игрока из зоны он ещё три секунды плывёт в ту сторону, где его видел в последний раз. Подсказка: не обнуляй Target мгновенно, а запусти таймер.

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

Квест пройден!

Враг видит, преследует и теряет цель — первый игровой ИИ работает. Грейд ЕГЕРЬ.

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

🏅 Забрать диплом Следующий квест: Три укуса
🔒

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

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

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