スマートフォンからさまざまな大画面フォーム ファクタに拡大する場合、ゲームがウィンドウ管理をどのように処理するかについて考慮する必要があります。ChromeOS と PC 版 Google Play Games では、ゲームをメインのデスクトップ インターフェースでウィンドウ モードで実行できます。Android 12L(API レベル 32)以降を搭載し、画面幅が 600 dp を超える新しい Android タブレットと折りたたみ式デバイスでは、ゲームを他のアプリと並べて分割画面モードで実行したり、サイズを変更したり、折りたたみ式デバイスの内側と外側のディスプレイ間で移動したりできます。これにより、ウィンドウ サイズと、一部のデバイスでは向きの構成が変更されます。
大画面の基本的な構成
ゲームがサイズ変更に対応できるかどうかを宣言します。
<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">
PC 版 Google Play Games
PC 版 Google Play Games では、指定されたアスペクト比を維持しながら、ウィンドウのサイズ変更が可能です。ウィンドウのサイズは、最適なサイズに自動的にロックされます。メインの向きが横向きの場合は 16:9 以上のアスペクト比をサポートする必要があります。ゲームが縦向きモードの場合は 9:16 のアスペクト比をサポートする必要があります。最適なエクスペリエンスを実現するには、横向きのゲームで 21:9、16:10、3:2 のアスペクト比を明示的にサポートしてください。ウィンドウのサイズ変更は必須ではありませんが、他のフォーム ファクタとの互換性を確保するために用意しておくことをおすすめします。
詳細とベスト プラクティスについては、PC 版 Google Play Games のグラフィックを設定するをご覧ください。
ChromeOS と Android の大画面
ChromeOS と大画面の Android デバイスでゲームの全画面表示の表示領域を最大化するには、全画面没入モードをサポートし、decorView
またはシステム UI の可視性にフラグを設定するか、WindowInsetsCompat
API を使用してシステムバーを非表示にします。また、ChromeOS デバイスで回転とサイズ変更の構成イベントを適切に処理するか、発生しないようにする必要があります。
大画面の Android デバイスでは、まだ対応していない構成でゲームが実行される可能性があります。ゲームがすべてのウィンドウ サイズと画面の向きの構成をサポートしていない場合、プラットフォームは互換モードでゲームをレターボックス表示し、必要に応じて、サポートされていない構成に変更する前にプレーヤーにプロンプトを表示します。

一部のデバイスでは、サポートされていない構成に移動すると、ゲームを再読み込みして新しいウィンドウ レイアウトに最適なアクティビティを再作成するオプションが表示され、ゲームプレイが中断されることがあります。さまざまなマルチウィンドウ モードの設定(2/3、1/2、1/3 のウィンドウ サイズ)でゲームをテストし、ゲームプレイや UI 要素が切り捨てられたり、アクセスできなくなったりしていないことを確認します。また、折りたたみ式デバイスのインナー ディスプレイとアウター ディスプレイを切り替えるときに、ゲームが折りたたみ式デバイスの継続性にどのように対応するかをテストします。問題が発生した場合は、これらの構成イベントを明示的に処理し、大画面の高度なサイズ変更サポートを追加します。
大画面の高度なサイズ変更
互換モードを終了してアクティビティの再作成を回避するには、次の操作を行います。
メイン アクティビティをサイズ変更可能として宣言します。
<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
をクエリして、デバイスの現在の回転を確認することもできます。このメタデータを使用して、新しいウィンドウのサイズを確認し、ウィンドウのサイズいっぱいにレンダリングします。アスペクト比が異なるため、この方法がすべてのケースで機能するとは限りません。その場合は、ゲーム UI を新しいウィンドウ サイズに固定し、コア ゲームプレイ コンテンツをレターボックス表示します。どちらのアプローチも技術的または設計上の制限により行えない場合は、独自のエンジン内レターボックスを使用してアスペクト比を維持し、resizeableActivity = false
を宣言して構成モードを回避しながら、可能な限り最適なサイズにスケーリングします。
どちらの方法を選択する場合でも、さまざまな構成でゲームをテストします(折りたたみと開き、さまざまな回転の変更、分割画面モード)。ゲーム内の UI 要素が切り捨てられたり重なったりしていないか、タップ対象のアクセス性に問題がないか、アスペクト比の問題でゲームが引き伸ばされたり、圧縮されたり、歪んだりしていないかを確認します。
また、画面が大きいほどピクセルも大きくなります。これは、同じ数のピクセルがはるかに広い領域に配置されるためです。これにより、サイズが小さくなったレンダリング バッファや解像度の低いアセットがモザイク状になる可能性があります。大画面デバイスで高品質のアセットを使用し、ゲームのパフォーマンス プロファイルを作成して問題がないことを確認します。ゲームで複数の品質レベルをサポートしている場合は、大画面デバイスに対応していることを確認してください。
マルチ ウィンドウ モード
マルチ ウィンドウ モードでは、複数のアプリで同じ画面を同時に使用できます。マルチウィンドウ モードはアクティビティのライフサイクルを変更しませんが、複数ウィンドウ内でのアプリの再開状態は Android のバージョンによって異なります(マルチウィンドウ モードをサポートするのマルチ ウィンドウ モードでのアクティビティのライフサイクルをご覧ください)。
プレーヤーがアプリまたはゲームをマルチウィンドウ モードに切り替えると、大画面のサイズ変更の詳細で説明されているように、構成の変更がアクティビティに通知されます。構成の変更は、プレーヤーがゲームのサイズを変更したときや、ゲームを全画面モードに戻したときにも発生します。
マルチ ウィンドウ モードに切り替えたときに、アプリがフォーカスを再取得する保証はありません。そのため、アプリの状態イベントを使用してゲームを一時停止する場合は、フォーカス取得イベント(フォーカス値が true の onWindowFocusChanged()
)に依存してゲームを再開しないでください。代わりに、onConfigurationChanged()
や onResume()
などの他のイベント ハンドラまたは状態変化ハンドラを使用してください。現在のアクティビティがマルチウィンドウ モードで実行されているかどうかは、いつでも isInMultiWindowMode()
メソッドを使用して検出できます。
ChromeOS のマルチウィンドウ モードでは、初期ウィンドウのサイズが重要な考慮事項になります。ゲームを全画面表示する必要はありません。その場合は、ウィンドウのサイズを宣言する必要があります。これに対処するには、次の 2 つの方法が推奨されます。
最初の方法では、Android マニフェストの <layout>
タグに特定の属性を使用します。defaultHeight
属性と defaultWidth
属性は、初期サイズを制御します。また、minHeight
属性と minWidth
属性にも注意し、プレーヤーがゲーム ウィンドウのサイズをサポートしていないサイズに変更できないようにします。最後に、gravity
属性があります。これは、起動時にウィンドウを画面上のどこに表示するかを決定します。これらの属性を使用したレイアウト タグの例を次に示します。
<layout android:defaultHeight="500dp"
android:defaultWidth="600dp"
android:gravity="top|end"
android:minHeight="450dp"
android:minWidth="300dp" />
ウィンドウ サイズを設定するための 2 つ目のオプションは、動的起動境界を使用します。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); }