Нажми — и увидишь, что делает команда
- ⏱ Сколько займёт
- 30–50 минут, 5 шагов. Каждый шаг заканчивается результатом на экране.
- 💻 Что нужно
- Компьютер с Windows или macOS. Понадобится Unity — бесплатная для учёбы, поставим на первом шаге. С телефона этот квест не проходится.
- ⏸ Если прервёшься
- Ничего не потеряется: прогресс сохраняется на этом устройстве. Вернёшься — продолжишь с того же шага.
- 🎓 Чему научишься
- враг из компонентов · зона зрения · преследование
В глубине живёт кто-то ещё
За песчаной банкой вода темнеет. Оттуда всплывает пузырь размером с голову.
«Ты был самым крупным ровно один день, — Марк не улыбается. — Там, внизу, есть крупнее».
Он не видит дальше своего носа. Но если ты войдёшь в его круг — пойдёт следом и не отстанет.
Ролик 3D и вид сверху — он показывает саму идею зоны зрения. У тебя будет 2D: круглый триггер вокруг врага и погоня, когда игрок в него вошёл. Надпись «ЗАМЕЧЕН» — необязательный бонус: заведи TMP-текст и включай его там же, где заполняется Target.
Читать текстом
Сегодня появится первый противник, который принимает решения.
И собирать мы его будем из отдельных маленьких скриптов, а не одного большого. Один отвечает за поворот, другой за глаза, третий за движение. Так проще чинить и переделывать.
Это называется компонентный подход: поведение раскладывают по деталям и собирают врагов как конструктор. Если проходил Godot: там ты бы написал один скрипт на узел — здесь привычнее иначе.
Глаза
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 промолчит — самый обидный вид ошибки.

- 1Hierarchy — собери врага целикомCreate Empty → назови Enemy. Внутри него ещё два пустых объекта: Eyes (большой круг зрения) и Mouth (маленький круг пасти).
- 2Tag — поставь акуле PlayerГлаза врага узнают героя только по тегу. Строка Tag — в самом верху Инспектора. Не поставил — враг смотрит сквозь тебя.
- 3Три скрипта врага — три Add ComponentEnemyEyes на объект Eyes, EnemyMovement и EnemyRotation на самого врага. Потом перетащи Eyes в поле eyes у скрипта движения. Add Component — в самом низу этого списка.
- 4Project — перетащи врага сюдаПолучится префаб. Расставь хоть десять врагов: поправишь заготовку — изменятся сразу все.
- 5Play — проверь, где он тебя замечаетПодплывай медленно. Пока не видит — плывёт по своим делам, увидел — разгоняется. Окно Game внизу слева.
Это настоящий экран Unity 6 — такой же, как у тебя. Нажимай на кружки по порядку: метка покажет место, строка ниже объяснит, зачем оно. Отмечай пройденное — прогресс сохранится.
Погоня
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 убирает из него длину, оставляя только направление.Заметь: враг в погоне быстрее, чем на прогулке. Так игрок чувствует момент, когда его заметили.
Враг ведёт себя странно: заметив игрока с другого конца карты, разгоняется до неприличия, а подплыв вплотную — почти останавливается. Найди строку.

Зона зрения: как враг «замечает»
Враг в игре не видит по-настоящему. Обычно вокруг него просто круг: вошёл в круг — значит замечен.
В играх про скрытность круг превращают в конус — как луч фонаря. Отсюда весь стелс: обойди сзади, и ты невидим.
Хорошие игры честно показывают момент обнаружения: знак над головой, звук, смена музыки. Иначе игрок считает, что его убили несправедливо.
Свой курс, когда никого нет
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; // анти-кувырок } }
GetComponent в Update — классическая причина тормозов, когда врагов становится много. И обрати внимание на последнюю строку: курс меняем только без цели, а flipY считаем всегда — иначе в погоне враг поплывёт кверху брюхом.Настрой опасность
- 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Поставь двух-трёх на картуНе больше: в маленьком море четыре хищника — это уже давка, а не игра.
Радиус зрения и разница скоростей — два числа, которые решают, будет игра честной или несправедливой.
Читать текстом
Задание студии: сделай, чтобы враг терял интерес не сразу. Пусть после выхода игрока из зоны он ещё три секунды плывёт в ту сторону, где его видел в последний раз. Подсказка: не обнуляй Target мгновенно, а запусти таймер.
Поднимай флаг.