Делаю «Вия» в вашей квартире: AR-хоррор на iPhone, Unity и реле кооператива на Cloudflare

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Привет, Хабр. Я делаю AR-хоррор для iPhone, называется Home Haunt. Сюжет — «Вий» Гоголя: бурсак Хома Брут три ночи читает над мёртвой панночкой в старой деревянной церкви. Только церковь вырастает не где-то на экране, а у вас в комнате. Ваши стены, ваш пол, ваш диван.

Игра сейчас в закрытом тесте в TestFlight. В статье — что получилось технически, где споткнулись и какие цифры намерили. Всё, что на гифках — реальная запись экрана iPhone, без вставок.

Стек

  • Unity 6 (6000.5), AR Foundation поверх ARKit, только iPhone.

  • Сборки из командной строки (-batchmode -executeMethod), выгрузка в TestFlight скриптом.

  • Кооператив — своё реле: сначала C# в Docker на маке, теперь Cloudflare Workers + Durable Objects.

  • Озвучка — локальные TTS (Kokoro для английского, Qwen для русского) + Gemini TTS на ключевые реплики, каждый дубль проверяем whisper'ом.

1. Скан комнаты — это часть игры, а не загрузка

Всё дальше опирается на настоящие плоскости: пол и стены. Поэтому сначала скан.

Как считаем готовность:

  • осмотр — 60 % прогресса (12 секторов по кругу, в каждый смотреть ~0,35 с);

  • найден пол — 25 %;

  • две стены (стена/дверь/окно считаются вместе) — 15 %.

Готово, когда прогресс ≥ 0,98 и осмотрены все 12 секторов. Если за 20 секунд ARKit не нашёл пол или две стены, или стена ближе 1,4 м — включается запасной режим, игра не застревает.

Что поняли: голый прогресс-бар убивает настроение. Сейчас Хома во время скана бормочет («сначала посмотри, где дверь, потом молись»), и те же 10 секунд ощущаются как осмотр чужого места, а не как загрузка.

2. Вещи на ваших стенах и переноска пальцем

После скана в комнате вырастает стол (1,0 × 0,6 м, высота 0,75 м) — рядом с вашим настоящим столом или в 1,2 м перед вами. А вещи Хомы появляются на ваших стенах: шапка висит на гвоздике на высоте 1,0–1,6 м, внутри найденной плоскости стены, не ближе 15 см к её краю.

Сначала вещи брались тапом. Это было скучно — AR превращается в меню. Переделали на переноску:

  • зажать вещь пальцем ≥ 0,25 с, и только если до неё ≤ 2 м (иначе «Подойди ближе»);

  • вещь висит перед камерой с весом (шапка лёгкая, люлька тяжёлая — качается по разному), телефон вибрирует;

  • несёшь к столу и отпускаешь в пределах 0,6 м от места — иначе падает на пол.

Так начинаешь ходить по квартире. А когда ходишь, пугаться своего коридора намного проще.

Под шапкой нацарапано «I · V · VII» — это номера свечей на полу. Свечу зажигаешь огарком: надо держать пламя над фитилём почти неподвижно.

Цифры, на которых остановились: пламя не дальше 0,14 м по горизонтали от фитиля, телефон движется медленнее 0,25 м/с, держать 0,3 с. Сначала было 0,25 м — и хватало просто провести огарком низко вдоль ряда, загорались все подряд.

3. Кровь по настоящим обоям

Когда все вещи на столе, комната «уходит»: темнеет, по стенам течёт кровь, из угла лезет нечисть и шепчет «Не смотри на стены, философ».

Для меня это самый сильный момент, хотя моделей тут меньше всего. Свои стены человек знает. Когда меняются они — работает лучше любой модели.

4. Тишина перед страхом

Первая сцена — дом Архивариуса в Киеве — вообще без пугалок. Свеча, письмо сотника, чёрная книга, Хома ворчит, что ехать не хочет. Механику туда я всё-таки добавлю, но тоже без пугалок. Правило такое: сначала история и тишина, потом кровь.

Дальше по сюжету изба старухи, казаки с загадками и рассказами, книга.

5. Страницы, которые смеются

В сцене «Страницы» вы ищете листы по комнате и раскладываете сюжет по порядку. Каждый найденный лист смеётся. Этот смех — мой, записал сам.

Разложил неправильно — шёпот «Не этот… тот, что раньше».

6. Гроб и ночь

У гроба гасишь свечи касанием пламени, ровную свечу — последней, иначе все загораются снова. Сейчас это слишком просто, переделываем на последовательность, которую надо угадать по загадкам в комнате.

В церкви — меловой круг на полу, книга с замком, код рисуешь пальцем на обложке, читаешь псалтырь голосом (микрофон) или ведёшь пальцем по строке.

7. Кооператив: два телефона, две квартиры

Идея: один играет Хому в церкви, другой — Юрко в «избе духов», каждый у себя дома. Ответ на загадку есть только у двоих вместе: у Юрко картина, у Хомы замок.

Сначала реле было на C# в Docker у меня на маке, наружу — через Cloudflare quick tunnel и Worker на relay.artuplabs.com. Работало, медиана доставки игрок → игрок 49–62 мс. Минус очевидный: мак должен быть включён.

Перенёс на Cloudflare Durable Objects (бесплатный план). Протокол и клиент не менял, адрес тот же. Что проверили:

  • кадры совпадают с C#-реле байт в байт — 122 из 122;

  • e2e 11 из 11, три раза подряд;

  • сброс объекта посреди сессии: клиенты вернулись за 3,7–3,8 с, без потерь.

Цена — задержка. Объект живёт в Варшаве, пинг 93–111 мс против 48 через мак. Доставка в smoke-тесте — 145 мс при нашем пороге 150. По LTE, скорее всего, будет выходить за порог, проверим на живых телефонах.

Что поняли на первом плейтесте вдвоём: пошаговый кооп не работает. Один делает — второй ждёт, и ждёт долго. Переделываем так, чтобы оба всегда были заняты, а промах одного мешал другому.

8. Озвучка

Реплик много, поэтому конвейер:

  • английский — Kokoro, русский — Qwen, локально;

  • ключевые реплики — Gemini TTS (бесплатная квота ~50 озвучек в день, поэтому порциями);

  • каждый дубль прогоняем whisper'ом и сверяем с текстом — так ловятся проглоченные слова;

  • ударения в русском правлю руками на своей странице: кликаешь гласную — она становится ударной («хомА»), правило можно отправить в словарь.

Отдельный трюк для Юрко из «Твин Пикса»: шум задом наперёд под репликой. Слова в итоге оставили обычными, а шум — перевёрнутым.

9. Бонус: почему трейлер дёргался

Монтировал трейлер из записей экрана и получил дёрганье. Оказалось, игра пишет кадры неравномерно — то 60, то 30–36 в секунду, с пропусками. При переводе в 30 fps на одном отрезке выпадало 63 кадра из 297, на другом 102 из 349. Решение — выводить в 60 fps без пропусков, а трясущиеся AR-куски стабилизировать с небольшим зумом.

Что дальше

  • кооператив без ожиданий;

  • головоломки вместо простых тапов (гроб, дом Архивариуса);

  • русская озвучка моим голосом для части героев.

Видео и новости игры: YouTube · TikTok · Instagram (@haunt_link)

Сайт: https://paledoorgames.artuplabs.com

Хотите в тест на iPhone — пишите на hello@artuplabs.com.

Буду рад вопросам, особенно про AR в маленьких комнатах — это была самая неприятная часть.

Источник: https://habr.com/ru/articles/1097844/


Интересные статьи

Интересные статьи

Центр информационной безопасности и мониторинга инцидентов «1С-Битрикс» добавил в программу «Безопасные интеграции» новый слой проверки подключаемых решений для маркетплейса от сторонних компаний-разр...
Когда CRM в Битрикс24 начинает открывать список сделок по 10 секунд, обычно первым делом подозревают сервер, нагрузку или саму платформу. Но на практике узкое место часто лежит ближе к базе: фильтры п...
MyCompany — это бесплатное и открытое решение для автоматизации малого и среднего бизнеса, построенное на платформе lsFusion. Мы уже рассказывали в блоге об этом решении и возможностях, которые оно пр...
В 2023 году Google выплатила $10 млн по своей глобальной программе багбаунти исследователям и белым хакерам за выявление уязвимостей в своих сервисах и проектах Chrome, Android, Google Play, продуктах...
Настройка любой площадки для CMS — это рутинный процесс, который должен быть доведен до автоматизма в каждой уважающей себя компании. А потому частенько воспринимается, как восход солнца — это происхо...