Розробка скриптів для процедурної генерації елементів у VR іграх
Ми розробляємо скрипти процедурної генерації для VR, де кожна деталь має витримувати тест з близької відстані. Користувач повертає голову — і бачить артефакти стикування тайлів, повторювані патерни або «плаваючі» колайдери. Це ламає імерсію миттєво. Вимоги до процедурного контенту у VR на порядок вищі, ніж у плоских іграх. Наші інженери мають 10+ років досвіду у VR-розробці та понад 50 реалізованих проєктів.
Головні технічні складності процедурної генерації у VR
Перша і найболючіша проблема — генерація геометрії у головному потоці. Mesh.SetVertices() + Mesh.RecalculateNormals() на 50 000 вершин в OnEnable займає 12–18 мс на Snapdragon XR2, що дає прямий frame drop нижче 72 FPS — поріг комфортного VR. Вирішується через Job System з IJobParallelFor та передачею даних через NativeArray<Vector3>, з подальшим застосуванням через Mesh.ApplyAndDisposeWritableMeshData() вже у головному потоці.
Друга проблема — колізії для процедурної геометрії. MeshCollider з convex: false на динамічно генерованому меші у Quest заборонений PhysX з міркувань продуктивності (і Oculus VRC його не пропустить). Або розбиваємо геометрію на випуклі примітиви, або генеруємо спрощений collision mesh окремо через алгоритм Quickhull. У складних сценах — замінюємо MeshCollider на масив BoxCollider/SphereCollider по вузлах генерованої структури.
Третя — детермінованість. Процедурна сцена має відтворюватися однаково при тому ж seed. Проблема виникає, коли генератор змішує Random.value (який залежить від глобального стану) та System.Random з фіксованим seed. Тримаємо весь генератор на одному екземплярі System.Random(seed) без звернень до UnityEngine.Random всередині пайплайну.
Чому процедурна генерація у VR складніша, ніж у плоских іграх?
Окрім технічних обмежень, VR потребує врахування фізіології: перепади висот більше 30° нахилу поверхні викликають дискомфорт при ходьбі з контролером. Ми інтегруємо slope-check прямо в генератор, обрізаючи екстремальні значення. Також критична швидкість: будь-який мікролаг при генерації руйнує ілюзію присутності. Тому ми гарантуємо, що кожен генератор проходить стрес-тест на 100+ сідах з виміром часу.
Як ми будуємо процедурні генератори для VR
Архітектура типового генератора для VR-рівня будується на трьох шарах: Layout Generator (розміщення ключових точок, шляхів, зон), Detail Populator (наповнення геометрією, мешами, асетами з пулу) та LOD Manager (управління деталізацією залежно від дистанції до HMD).
Для генерації terrain-подібних структур використовуємо Perlin Noise через Mathf.PerlinNoise() з октавами — стандарт, але у VR важливий діапазон висот. Для міських та інтер'єрних сцен працює BSP (Binary Space Partitioning) або Wave Function Collapse — WFC особливо гарний для тайлових рівнів з чіткими правилами стикування. WFC працює ефективніше pure BSP у 2–3 рази за швидкістю збірки на складних constraints. Реалізуємо WFC з backtracking, обмеженим по depth, щоб не піти у безкінечний перебір.
З реального кейсу: у проєкті архітектурної VR-візуалізації генератор планування квартир на базі WFC спочатку давав 40% випадків з «невалідними» планами (кімната без виходу, стіни, що перетинаються). Виправили додаванням pre-pass валідатора з правилами зв'язності через BFS по графу кімнат — перед фінальною матеріалізацією меша.
Пул об'єктів критичний. Інстанціювання 500 GameObject через Instantiate() при зміні рівня — 200–400 мс фриз. Використовуємо ObjectPool<T> з UnityEngine.Pool (доступний з Unity 2021), попередньо наповнений у фоновому потоці через AsyncInstantiateOperation.
Як уникнути падіння FPS при генерації геометрії?
Основний прийом — винесення обчислень з головного потоку. Ми використовуємо Job System для всіх операцій з вершинами та колізіями. Додатково налаштовуємо LOD для генерованої геометрії: на далеких дистанціях замінюємо складні меші на спрощені колайдери. Це дозволяє зберігати 72+ FPS навіть на мобільних HMD.
Етапи роботи
- Аналіз контенту. Вивчаємо, що саме потрібно генерувати: геометрія, розстановка об'єктів, наратив, навігація. Від цього залежить вибір алгоритму.
- Прототип генератора. Швидка реалізація з візуалізацією в Editor-режимі через Gizmos — клієнт бачить результат без збірки під HMD.
- Оптимізація під VR. Перенесення обчислень у Job System, реалізація пулу, налаштування LOD для генерованої геометрії.
- Інтеграція з рівнем. Підключення до NavMesh (baking після генерації через NavMeshSurface.BuildNavMesh()), налаштування Occlusion Culling для процедурних об'єктів.
- Тестування. Стрес-тест: 100 генерацій з різними seed, перевірка на артефакти, валідація колізій, вимір часу генерації на цільовому HMD.
Терміни розробки генераторів
| Тип генератора | Терміни розробки |
|---|---|
| Розстановка об'єктів за правилами (без геометрії) | 3–7 днів |
| Тайловий рівень з WFC | 2–3 тижні |
| Процедурна геометрія з Job System | 3–5 тижнів |
| Повний генератор рівня з NavMesh та LOD | 1–3 місяці |
Типові помилки та їх вирішення
| Помилка | Вирішення |
|---|---|
| Нестабільний FPS при генерації | Job System + пул об'єктів |
| Невалідні плани (WFC) | Pre-pass валідатор з BFS |
| Плаваючі колайдери | Quickhull або складові колайдери |
Що входить в роботу
- Аналіз вимог та вибір алгоритму.
- Розробка прототипу та демонстрація в редакторі.
- Реалізація production-версії з оптимізацією під VR.
- Інтеграція з рівнем (NavMesh, Occlusion Culling).
- Стрес-тестування (100+ сідів) та валідація.
- Документація по seed-управлінню та підтримці.
- За бажанням — навчання команди.
Вартість визначається після розбору технічного завдання та оцінки складності алгоритміки. Отримайте консультацію по вашому проєкту — наші інженери оцінять складність та запропонують оптимальний алгоритм.






