tags: [vr-ar]
Програмування ІШ врагів для навігації у 3D просторі ігор
NavMeshAgent застрив у кутку. Або ходить по колу навколо перешкоди, коли міг би обійти за секунду. Або телепортується крізь стіну при зміні сцени. Проблеми навігації ІШ у 3D — не «що-то пішло не так», а конкретні архітектурні рішення, які або враховують обмеження NavMesh, або ні.
У VR специфіка гостріша: гравець фізично знаходиться у просторі гри, передвигається сам, і враги мають реагувати на цей рух миттєво. Враг, який «подумав» 200 мс перед поворотом, у VR помітний як ніколи.
Типові відмови NavMeshAgent та їх причини
Застревання на стику NavMeshSurface. Якщо сцена використовує кілька NavMeshSurface (різні області, різні рівні), агент застряває при переході між ними. Причина — стики NavMesh не сшиваються автоматично. Потрібно або використовувати єдину поверхню з NavMeshLink для мостів між ними, або явно додавати NavMeshLink компоненти на точках переходу.
Агент не оновлює шлях при русі гравця. SetDestination викликається один раз при виявленні гравця, і агент йде до тієї точки, де гравець був. Потрібно periodic path update — кожні 0.2–0.5 секунди викликати SetDestination з поточною позицією цілі. Надто часто — CPU overhead від постійного пересчету шляху. Надто рідко — враг «відстає». Компромісс: оновлювати тільки якщо ціль переміститась на destinationChangeThreshold метрів.
Агент проходить крізь інших агентів. NavMeshAgent.radius — це радіус для NavMesh obstacle avoidance, але працює тільки з NavMeshObstacle та іншими агентами. Якщо агент має нижчу avoidancePriority, він поступається і може «вдавлюватися» у об'єкти. Розставляємо пріоритети: рядові враги — 50, боси — 20, гравець — 10 (вищий пріоритет = менше число = інші поступаються).
Steering Behaviour поверх NavMesh
NavMesh дає глобальний шлях від A до B. Але рух по цьому шляху — окрема задача. Стандартний NavMeshAgent.steeringTarget — наступна точка шляху — може давати кутастий рух: агент робить різкий поворот на 90° замість плавного.
Рішення: відключити NavMeshAgent.updateRotation, і обертати агента самостійно через Quaternion.RotateTowards з кутовою швидкістю, що відповідає характеру персонажа. Повільний зомбі — 60°/сек. Швидкий боєць — 180°/сек. Одразу робить рух переконливіше.
Для складнішої поведінки — Steering Behaviours поверх NavMesh: Seek (до цілі), Flee (від цілі), Separation (розходитися від сородичів). Separation особливо важливий для групи врагів у VR — без нього вони всі телепортуються в одну точку, що виглядає нереалістично. Separation реалізується як додаткова сила, додавана до бажаної швидкості: беремо всіх агентів у радіусі separationRadius, сумуємо вектори «від кожного», нормалізуємо та додаємо як зміщення до NavMeshAgent.velocity.
Behaviour Tree vs State Machine для VR-врагів
State Machine (через Animator Controller з параметрами або через код) — простіше в реалізації, але погано масштабується. При 5+ станах переходи перетворюються у спагеті.
Behaviour Tree (BT) — іерархічна структура задач. Враг: Selector → [Attack якщо дистанція < 2м → Chase якщо бачить гравця → Patrol інакше]. Кожен вузол — Sequence (всі дочірні мають успіти), Selector (достатньо одного успішного), або Leaf (конкретна дія). У Unity немає вбудованого BT, але є пакет Behavior (від Unity, 2024+) або відкриті NPBehave, Fluid Behaviour Tree.
Для VR важливо: BT мають оновлюватися з різною частотою залежно від дистанції до гравця. Враг у 30 м — оновлення BT раз на секунду. Враг у 3 м — кожні 100 мс. LOD-driven AI update rate через AIDirector або простий DistanceBasedUpdateRate компонент знижує CPU-навантаження від множини активних агентів.
Пространственна освідомленість: слух та зір
Vision cone реалізується через Physics.OverlapSphere + кутова перевірка + Linecast для перевірки видимості. Стандартний підхід: збираємо всі потенціальні цілі у радіусі sightRange, фільтруємо за Vector3.Angle < fieldOfView / 2, перевіряємо Linecast на перешкоди — перша непересічена — ціль виявлена.
Для VR-ігор додаємо перевірку звукових стимулів: гравець стріляє або біжить → створюється подія SoundStimulus з позицією та інтенсивністю → всі агенти у радіусі intensity * attenuationFactor отримують сповіщення. Можна реалізувати через Unity Events або простий Physics.OverlapSphere з точки звуку.
| Складність ІШ | Орієнтовні строки |
|---|---|
| Базова навігація (NavMeshAgent + chase/patrol) | 1–2 тижні |
| Behaviour Tree + групи врагів + Steering | 3–6 тижнів |
| Повна AI-система з сприйняттям та LOD | 2–4 місяці |
Вартість розраховується після аналізу вимог до поведінки врагів та числа одночасно активних агентів.





