支援大螢幕大小調整功能

從手機擴展到不同的大螢幕板型規格時,您需要考慮遊戲如何處理視窗管理。在 Googlebook、ChromeOS 和 Google Play 遊戲電腦版上,遊戲可以在主桌面介面以視窗模式執行。在搭載 Android 12L (API 級別 32) 以上版本且螢幕寬度大於 600 dp 的新 Android 平板電腦和摺疊式裝置上,您的遊戲可以與其他應用程式並排執行於分割畫面模式,還能調整大小,甚至在摺疊式裝置的內外螢幕之間移動,導致視窗大小和螢幕方向 (在某些裝置上) 發生設定變更。

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 Games 電腦版

如果是 Google Play 遊戲電腦版,平台會處理視窗大小調整作業,同時遵守指定的顯示比例。視窗大小會自動鎖定為最佳尺寸。如果主要螢幕方向為橫向,您至少需要支援 16:9 的顯示比例;如果遊戲為直向模式,則至少需要支援 9:16 的顯示比例。為獲得最佳體驗,請明確支援橫向遊戲的 21:9、16:10 和 3:2 顯示比例。這裡不需要視窗大小調整功能,但為了相容於其他裝置類型,最好還是要有這項功能。

如需詳細資訊和最佳做法,請參閱「設定 Google Play 遊戲電腦版的圖形功能」。

大螢幕

如要在平板電腦、摺疊式裝置、Googlebook、ChromeOS 和連線螢幕上,以全螢幕模式盡可能擴大遊戲的可視區域,請支援全螢幕沉浸模式,並透過在 decorView、系統 UI 可見度或 WindowInsetsCompat API 上設定旗標,隱藏系統資訊列。您也應妥善處理旋轉和調整大小的設定事件,或避免發生這類事件。

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

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

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

進階大螢幕可調整大小功能

圖 2. 電腦和桌面型態的折疊式裝置上顯示不同的 UI。

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

  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() 方法,偵測目前的活動是否在多視窗模式下執行。

在 Googlebook、ChromeOS、大螢幕平板電腦和摺疊式裝置上使用電腦分割視窗模式時,初始視窗尺寸就成為重要的考量因素。遊戲不一定要全螢幕顯示,您需要為這種情況宣告視窗大小。建議您採取下列兩種做法。

第一種做法是在 Android 資訊清單的 <layout> 標記中使用特定屬性。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 版面配置程式庫支援桌面等折疊式裝置型態,提升播放器的沉浸感和參與度:

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