Motion sickness виникає, коли затримка візуального відгуку перевищує 20 мс. На Google Cardboard IMU працює на 200–1000 Гц, а рендеринг — лише 60 Гц. Використовуйте head tracking IMU для синхронізації. Ми розробляємо VR-додатки для Cardboard на iOS та Android з використанням Swift та Kotlin. Наш досвід — 5 років у мобільній VR-розробці, понад 20 проєктів. Ми гарантуємо якість та підтримку після публікації. Далі розберемо ключові технічні задачі та їх вирішення.
Як уникнути motion sickness у Google Cardboard?
Motion sickness виникає, коли visual latency > 20ms. IMU працює на 200–1000Hz, але рендеринг на 60Hz. Для компенсації використовується ATW (Asynchronous TimeWarp) — перепроєкція останнього кадру з урахуванням нової орієнтації голови за час між рендером та виведенням на екран. У Cardboard SDK ATW реалізований автоматично. (джерело: Google Cardboard SDK) Переконайтеся, що Cardboard.SDK.UpdateScreenParams() викликається на початку кожного Update(), а не рідше.
Рекомендації по Scene Design для зниження заколисування:
- Немає acceleration-based locomotion (телепортація краща) — телепортація в 10 разів комфортніша за плавне переміщення для користувачів.
- Постійний горизонт або cockpit-reference (кабіна, інтер'єр) знижують дискомфорт
- Не масштабуйте світ відносно гравця в рантаймі
Як реалізувати стереоскопічний рендеринг?
Екран ділиться навпіл (split screen VR). Ліва половина — для лівого ока, права — для правого. Кожна половина рендериться з невеликим зміщенням камери (IPD — interpupillary distance, ~63–65mm). Різниця між двома зображеннями створює стереоефект.
У Unity це керується через компонент CardboardCamera з двома рендер-текстурами. Кожна текстура рендериться окремо, потім застосовується barrel distortion correction.
Критична проблема продуктивності: two-pass rendering подвоює навантаження на GPU. На середньому смартфоні при 1080p це 30–40 FPS без оптимізацій. Рішення:
- Foveated rendering — зниження роздільної здатності по краях екрану (не центральна область видно через лінзи)
- Single Pass Instanced Rendering в Unity (рендеринг обох очей за один draw call). Цей метод в 2 рази швидше за two-pass.
- Зниження роздільної здатності рендер-текстур до 0.7–0.8 від екранної роздільної здатності
| Метод | FPS (1080p, середній смартфон) | Якість зображення |
|---|---|---|
| Two-pass | 30–40 | Повна роздільна здатність |
| Single Pass Instanced | 55–60 | Повна роздільна здатність |
| Foveated + Single Pass | 60+ | Знижена по краях |
Як інтегрувати Cardboard SDK?
Після того як Google відкрив вихідні коди Cardboard SDK, він став офіційним шляхом для Cardboard-додатків на iOS та Android. Для розробки під iOS VR використовуйте Swift, для Android — Kotlin. VR розробка на Swift та Kotlin включає:
- Дисторсію-корекцію для лінз (кожен корпус має свій lens distortion profile, що сканується QR-кодом)
- Head tracking через ф'южн даних акселерометра та гіроскопа (IMU fusion)
- Eye matrices для коректної проєкції на кожне око
- Trigger button обробку (магнітна кнопка в картонному Cardboard)
Інтеграція Unity — com.google.cardboard UPM пакет. Після підключення:
Code example (Unity)
void Update() {
Cardboard.SDK.UpdateScreenParams();
// Позиція/ротація голови застосовується автоматично через CardboardCamera компонент
}
Нативна Android інтеграція через CardboardHeadTracker та CardboardLensDistortion:
Code example (Android/Kotlin)
headTracker = CardboardHeadTracker.create();
lensDistortion = CardboardLensDistortion.create(encodedDeviceParams, width, height);
headTracker.getPose(monotonic_time_nanos, target_time_nanos, outEyeFromHead);
Ввід: кнопка та Gaze
У базового Cardboard одна кнопка. Вся взаємодія будується на:
- Gaze input — курсор слідує за поглядом, активація по фіксації погляду (dwell time, зазвичай 1.5–2 сек)
- Trigger button — підтвердження вибору, телепортація
Gaze reticle рендериться в world space на фіксованій відстані від камери. Raycast з центру кожного ока визначає об'єкт під курсором:
Code example (Gaze input)
void Update() {
Ray ray = new Ray(Camera.main.transform.position, Camera.main.transform.forward);
if (Physics.Raycast(ray, out RaycastHit hit, maxDistance, interactableLayer)) {
gazeTarget = hit.collider.GetComponent<IGazeable>();
gazeTarget?.OnGazeEnter();
gazeTimer += Time.deltaTime;
if (gazeTimer >= DWELL_TIME) {
gazeTarget?.OnGazeActivate();
gazeTimer = 0f;
}
} else {
gazeTarget?.OnGazeExit();
gazeTimer = 0f;
}
}
QR-сканування профілю пристрою
При першому запуску користувач сканує QR-код з корпусу Cardboard. SDK завантажує lens distortion profile для конкретного корпусу. Без цього кроку спотворення некоректне — зображення виглядає деформованим. Cardboard SDK зберігає профіль у SharedPreferences / NSUserDefaults після сканування. Додайте на перший екран інструкцію з іконкою QR і явну кнопку «повторно відсканувати пристрій» у налаштуваннях.
Що входить у роботу
- Вихідний код додатка з коментарями
- Документування API та ключових компонентів
- Інструкція з QR-сканування для користувачів
- Підтримка при публікації в App Store та Google Play
- Тестування на 5+ пристроях різних цінових сегментів
Процес роботи
- Аналіз: визначення типу додатка (пасивний досвід чи інтерактивний), цільової аудиторії та вимог до продуктивності.
- Налаштування Cardboard SDK: підключення Unity пакета або нативна інтеграція, конфігурація проєкції.
- Розробка сцени: моделювання з урахуванням VR-обмежень, реалізація gaze input.
- Оптимізація: Single Pass Instanced, foveated rendering, LOD, тестування FPS.
- Тестування на пристроях різних цінових сегментів, оцінка комфорту.
- Деплой: підготовка білдів, завантаження в App Store Connect та Google Play Console.
Орієнтири по термінах
Простий пасивний VR-досвід (360-контент, базова навігація поглядом) — 1–2 тижні. Вартість — від $200. Інтерактивний VR-додаток з ігровою механікою, множиною сцен та повним UI — 2–3 місяці. Вартість — від $5000.
Оцініть ваш проєкт: зв'яжіться з нами для попереднього розрахунку термінів та вартості. Замовте розробку мобільного VR-додатка під Google Cardboard — отримайте консультацію інженера з 5-річним досвідом.







