Решили: при выходе с карты мировой вид ВОЗВРАЩАЕТ кадр, оставленный перед входом на неё, а не подхватывает живой. EnterMap запоминает кадр мира, ExitMap его восстанавливает и входит в режим с adoptLiveFrame: false.

Почему: живой кадр в момент выхода принадлежит КАРТЕ — она живёт своей зоной за сотни единиц от арены (CM Map стояла в y≈240). AdoptLiveFrame брал его и прижимал клампом к краю зоны камеры, из-за чего свободная камера оказывалась в (−19.94, 23.41) — в пустоте над ареной. Игрок выходил из карты в синее ничто.

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

Грабли:

  • Зона камеры вчетверо больше поля (80×60 против 39×26 у ArenaLayoutAuthoring), поэтому кламп не ловил уезд: центр кадра волен гулять почти на тридцать единиц от арены. С зоной по размеру поля баг выглядел бы как лёгкий сдвиг, а не как пустой экран.
  • Симптом «боя нет» не про бой. На расстановке фаза не Fighting, поэтому правит свободный вид (Overview); в бою включается следящая CM Action, и она встаёт по юнитам сама. Отсюда «на расстановке пусто, а в бою всё ок» — и отсюда же ложный след про скоупы: кадр ленты был полон, виды созданы, паспорта на месте.
  • Различить «юниты не там» и «камера не туда» по логу было нечем — обе картинки одинаковы. В heartbeat диагностики добавлены габариты юнитов и позиция камеры; ответ теперь читается одной строкой.

Владелец правды: Presentation/Camera/CameraModeController.cs (RememberWorldFrame / RestoreWorldFrame).