При адаптации игры для устройств с большими экранами необходимо учитывать, как она будет работать с окнами. На Googlebook, ChromeOS и в Google Play Games на компьютере игра может запускаться в оконном режиме поверх основного интерфейса рабочего стола. На новых планшетах Android и складных устройствах с Android 12L (уровень API 32) или более поздней версией и шириной экрана > 600 dp игра может работать в режиме разделения экрана вместе с другими приложениями. Ее размер можно изменить, а на складных устройствах – даже перемещать между внутренним и внешним экранами. Это приводит к изменению размера окна и, на некоторых устройствах, ориентации.
Изменение размера окон в играх на Unity
Базовая конфигурация для больших экранов
Укажите, поддерживает ли игра изменение размера:
<android:resizeableActivity="true" or "false" />
Если вы не можете обеспечить поддержку изменения размера, убедитесь, что в манифесте игры явно определены минимальное и максимальное поддерживаемые соотношения сторон:
<!-- Render full screen between 3:2 and 21:9 aspect ratio -->
<!-- Let the platform letterbox otherwise -->
<activity android:minAspectRatio="1.5">
<activity android:maxAspectRatio="2.33">
Google Play Игры на компьютере
В Google Play Играх на компьютере платформа позволяет изменять размер окна, сохраняя заданное соотношение сторон. Размер окна автоматически фиксируется на оптимальных значениях. Если основная ориентация игры горизонтальная, необходимо поддерживать соотношение сторон не менее 16:9, а если вертикальная – не менее 9:16. Для наилучшего результата обеспечьте поддержку соотношений сторон 21:9, 16:10 и 3:2 для игр с горизонтальной ориентацией. Изменение размера окна не требуется, но может быть полезно для совместимости с другими типами устройств.
Дополнительную информацию и рекомендации можно найти в статье Как настроить графику для Google Play Игр на компьютере.
Большие экраны
Чтобы максимально увеличить видимую область игры в полноэкранном режиме на планшетах с большим экраном, складных устройствах, Googlebook, ChromeOS и подключенных дисплеях, поддерживайте полноэкранный режим погружения и скрывайте системные панели, устанавливая флажки в decorView, видимости системного интерфейса или через API WindowInsetsCompat. Также необходимо корректно обрабатывать события изменения размера и поворота экрана или предотвращать их.
Обратите внимание, что на устройствах Android с большим экраном игра может запускаться в конфигурациях, которые вы ещё не поддерживаете. Если игра поддерживает не все размеры окон и ориентации, платформа кашетирует ее в режиме совместимости и при необходимости запрашивает у игрока подтверждение, прежде чем переключиться на неподдерживаемую конфигурацию.
На некоторых устройствах при переходе к неподдерживаемой конфигурации игроку может быть предложено перезагрузить игру и воссоздать действие, чтобы оно соответствовало новому макету окна. Это нарушает игровой процесс. Протестируйте игру в разных конфигурациях многооконного режима (размер окна 2/3, 1/2, 1/3) и убедитесь, что элементы геймплея и интерфейса не обрезаются и остаются доступными. Кроме того, проверьте, как игра реагирует на переключение между внутренним и внешним экранами на складных устройствах. Если вы обнаружите проблемы, обработайте эти события конфигурации и добавьте расширенную поддержку изменения размера для больших экранов.
Расширенные возможности изменения размера на больших экранах
Чтобы выйти из режима совместимости и избежать повторного создания действия, выполните следующие действия:
Объявите, что размер основного действия можно изменять:
<android:resizeableActivity="true" />Чтобы получать все события конфигурации большого экрана, в манифесте игры в элементе
<activity>добавьте атрибутandroid:configChangesсо значениями orientation, screenSize, smallestScreenSize, screenLayout и density.<android:configChanges="screenSize | smallestScreenSize | screenLayout | orientation | keyboard | keyboardHidden | density" />Переопределите
onConfigurationChanged()и обработайте событие конфигурации, включая текущую ориентацию, размер окна, ширину и высоту:Kotlin
override fun onConfigurationChanged(newConfig: Configuration) { super.onConfigurationChanged(newConfig) val density: Float = resources.displayMetrics.density val newScreenWidthPixels = (newConfig.screenWidthDp * density).toInt() val newScreenHeightPixels = (newConfig.screenHeightDp * density).toInt() // Configuration.ORIENTATION_PORTRAIT or ORIENTATION_LANDSCAPE val newScreenOrientation: Int = newConfig.orientation // ROTATION_0, ROTATION_90, ROTATION_180, or ROTATION_270 val newScreenRotation: Int = windowManager.defaultDisplay.rotation }
Java
@Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); float density = getResources().getDisplayMetrics().density; int newScreenWidthPixels = (int) (newConfig.screenWidthDp * density); int newScreenHeightPixels = (int) (newConfig.screenHeightDp * density); // Configuration.ORIENTATION_PORTRAIT or ORIENTATION_LANDSCAPE int newScreenOrientation = newConfig.orientation; // ROTATION_0, ROTATION_90, ROTATION_180, or ROTATION_270 int newScreenRotation = getWindowManager().getDefaultDisplay() .getRotation(); }
Вы также можете запросить WindowManager, чтобы проверить текущую ориентацию устройства. Используя эти метаданные, проверьте новые размеры окна и выполните рендеринг в полноэкранном режиме. Это может не сработать из-за разницы в соотношении сторон. В таком случае привяжите интерфейс игры к новому размеру окна и добавьте черные полосы по краям основного контента. Если технические или дизайнерские ограничения не позволяют использовать ни один из этих подходов, выполните кашетирование в движке, чтобы сохранить соотношение сторон, и масштабируйте до наилучших возможных размеров, объявив resizeableActivity = false и избегая режима конфигурации.
Какой бы подход вы ни выбрали, протестируйте игру в разных конфигурациях (в сложенном и разложенном виде, при повороте экрана, в режиме разделенного экрана). Убедитесь, что элементы интерфейса не обрезаются и не перекрывают друг друга, области прикосновения доступны, а соотношение сторон не искажает изображение.
Кроме того, на больших экранах пиксели обычно крупнее, поскольку их количество остается прежним, а площадь экрана увеличивается. Это может привести к пикселизации уменьшенных буферов рендеринга или объектов с низким разрешением. Используйте объекты самого высокого качества на устройствах с большим экраном и проверьте производительность игры, чтобы убедиться в отсутствии проблем. Если в игре есть несколько уровней качества, убедитесь, что они подходят для устройств с большим экраном.
Многооконный режим
Многооконный режим позволяет одновременно использовать несколько приложений на одном экране. Многооконный режим не влияет на жизненный цикл объекта activity, однако состояние возобновления приложений в нескольких окнах различается в зависимости от версии Android (см. раздел Жизненный цикл объекта activity в многооконном режиме в статье Поддержка многооконного режима).
Когда игрок переводит приложение или игру в многооконный режим, система уведомляет объект activity об изменении конфигурации, как описано в разделе Расширенные возможности изменения размера окон на больших экранах. Изменение конфигурации также происходит, когда игрок меняет размер окна игры или возвращает ее в полноэкранный режим.
Нет гарантии, что приложение снова окажется в фокусе, когда будет переведено в многооконный режим. Поэтому, если вы используете события состояния приложения, чтобы приостановить игру, не полагайтесь на событие получения фокуса (onWindowFocusChanged() со значением true), чтобы возобновить ее. Вместо этого используйте другие обработчики событий или изменений состояния, например onConfigurationChanged() или onResume(). Обратите внимание, что вы всегда можете использовать метод isInMultiWindowMode(), чтобы определить, запущено ли текущее действие в многооконном режиме.
При использовании многооконного режима на устройствах Googlebook, ChromeOS, планшетах с большим экраном и складных устройствах важно учитывать начальные размеры окна. Игра не обязательно должна быть в полноэкранном режиме, и в этом случае вам нужно будет объявить, каким должен быть размер окна. Есть два способа сделать это.
Первый вариант предполагает использование определенных атрибутов в теге <layout> в манифесте Android. Атрибуты defaultHeight и defaultWidth определяют исходные размеры. Также обратите внимание на атрибуты minHeight и minWidth, чтобы игроки не могли изменить размер окна игры на неподдерживаемый. Наконец, атрибут gravity определяет, в какой части экрана будет появляться окно при запуске. Пример тега макета с этими атрибутами:
<layout android:defaultHeight="500dp"
android:defaultWidth="600dp"
android:gravity="top|end"
android:minHeight="450dp"
android:minWidth="300dp" />
Второй вариант настройки размера окна – использование динамических границ запуска. С помощью setLaunchBounds(Rect) можно задать размеры окна при запуске. Если указан пустой прямоугольник, действие запускается в развернутом состоянии.
Если вы используете игровые движки Unity или Unreal, убедитесь, что у вас установлена последняя версия (Unity 2019.4.40 и Unreal 5.3 или более поздняя), которая обеспечивает хорошую поддержку многооконного режима.
Поддержка складных устройств
Используйте библиотеку макетов Jetpack WindowManager для поддержки складных устройств в настольном режиме, например планшетов, чтобы повысить вовлеченность игроков.
Kotlin
fun isTableTopPosture(foldFeature : FoldingFeature?) : Boolean { contract { returns(true) implies (foldFeature != null) } return foldFeature?.state == FoldingFeature.State.HALF_OPENED && foldFeature.orientation == FoldingFeature.Orientation.HORIZONTAL }
Java
boolean isTableTopPosture(FoldingFeature foldFeature) { return (foldFeature != null) && (foldFeature.getState() == FoldingFeature.State.HALF_OPENED) && (foldFeature.getOrientation() == FoldingFeature.Orientation.HORIZONTAL); }