支援大螢幕大小調整功能

從手機擴展到不同大螢幕板型規格時,您必須考量遊戲如何處理視窗管理作業。在 ChromeOSGoogle Play 遊戲電腦版 上,遊戲可透過主要桌面介面以視窗模式執行。在搭載 Android 12L (API 級別 32) 以上版本的新款 Android 平板電腦和折疊式裝置上,如果螢幕寬度大於 600dp,遊戲可以與其他應用程式在分割畫面模式中並排執行,並且可調整大小,甚至在折疊式裝置的內外螢幕之間移動,進而變更視窗大小,並在某些裝置上變更螢幕方向。

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 遊戲電腦版的圖形功能」。

ChromeOS 和 Android 大螢幕

如要在 ChromeOS 和大螢幕 Android 裝置上以全螢幕模式顯示遊戲,請支援全螢幕沉浸式模式,並在 decorView 或系統 UI 顯示設定標記,或是透過 WindowInsetsCompat API 隱藏系統列。您也應妥善處理旋轉和調整大小設定事件,或避免這些事件在 ChromeOS 裝置上發生。

請注意,在大型螢幕 Android 裝置上,遊戲可能會在您尚未處理的設定下執行。如果遊戲不支援所有視窗大小和方向設定,平台會在相容性模式中為遊戲加上黑邊,並在必要時在變更為不支援的設定前,向玩家顯示提示。

圖 1. 設定相容性對話方塊。

在某些裝置上,當玩家移至不支援的設定時,系統可能會提示玩家選擇重新載入遊戲,並重新建立活動,以便盡可能配合新的視窗版面配置,這會影響遊戲體驗。請在各種多視窗模式設定 (2/3、1/2、1/3 視窗大小) 下測試遊戲,並確認遊戲過程或 UI 元素不會遭到截斷或無法存取。此外,請測試遊戲在折疊式裝置上,在內螢幕和外螢幕之間切換時,如何回應折疊式連續性。如果發現問題,請明確處理這些設定事件,並新增進階大螢幕可調整大小支援功能。

進階大螢幕調整大小功能

圖 2. 在電腦和折疊式裝置的桌面型態中,使用不同的使用者介面。

如要退出相容性模式並避免重新建立活動,請執行下列操作:

  1. 將主要活動宣告為可調整大小:

    <android:resizeableActivity="true" />
    
  2. 在遊戲資訊清單 <activity> 元素的 android:configChanges 屬性中,明確宣告支援「orientation」、「screenSize」、「smallestScreenSize」、「screenLayout」和「density」,以便接收所有大螢幕設定事件

    <android:configChanges="screenSize | smallestScreenSize | screenLayout | orientation | keyboard |
                            keyboardHidden | density" />
    
  3. 覆寫 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 版本而異 (請參閱「支援多視窗模式」中的「多視窗模式中的活動生命週期」)。

如果玩家將應用程式或遊戲設為多視窗模式,系統會向活動發出通知,說明設定已變更。想進一步瞭解如何處理大螢幕的進階調整大小功能,請參閱這篇文章。當玩家調整遊戲大小或將遊戲重新置於全螢幕模式時,也會發生設定變更。

應用程式進入多視窗模式時,無法保證會重新取得焦點。因此,如果您使用任何應用程式狀態事件暫停遊戲,請勿依賴取得焦點事件 (onWindowFocusChanged(),焦點值為 true) 來繼續遊戲。請改用其他事件處理常式或狀態變更處理常式,例如 onConfigurationChanged()onResume()。請注意,您隨時可以使用 isInMultiWindowMode() 方法,偵測目前活動是否在多視窗模式下執行。

在 ChromeOS 的多視窗模式下,初始視窗尺寸就成了重要的考量因素。遊戲不必全螢幕顯示,您需要宣告在這種情況下視窗的大小。建議您採用下列兩種方法。

第一個選項會在 Android 資訊清單的 <layout> 標記上使用特定屬性。defaultHeightdefaultWidth 屬性會控制初始尺寸。請注意 minHeightminWidth 屬性,避免玩家將遊戲視窗大小調整為您不支援的尺寸。最後,還有 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 版面配置程式庫支援折疊式型態 (例如桌面模式),提高玩家的沉浸感和參與度:

圖 3. 遊戲以免手持模式顯示,主畫面顯示在螢幕的垂直部分,控制項則顯示在水平部分。

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);
}