Việc mở rộng từ điện thoại sang các kiểu dáng màn hình lớn khác nhau sẽ đưa ra các cân nhắc về cách trò chơi của bạn xử lý việc quản lý cửa sổ. Trên ChromeOS và Google Play Games trên máy tính, trò chơi của bạn có thể chạy ở chế độ cửa sổ thông qua giao diện chính của máy tính. Trên máy tính bảng Android và thiết bị có thể gập lại mới chạy Android 12L (API cấp 32) trở lên với chiều rộng màn hình > 600 dp, trò chơi của bạn có thể chạy cạnh nhau ở chế độ chia đôi màn hình với các ứng dụng khác, có thể đổi kích thước và thậm chí được di chuyển giữa màn hình trong và màn hình ngoài trên thiết bị có thể gập lại, dẫn đến sự thay đổi về cấu hình cho kích thước cửa sổ và hướng trên một số thiết bị.
Khả năng đổi kích thước với các trò chơi Unity
Cấu hình màn hình lớn cơ bản
Khai báo xem trò chơi của bạn có xử lý được khả năng đổi kích thước hay không:
<android:resizeableActivity="true" or "false" />
Nếu không hỗ trợ khả năng đổi kích thước, hãy đảm bảo tệp kê khai trò chơi xác định rõ tỷ lệ khung hình tối thiểu và tối đa được hỗ trợ:
<!-- 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 trên máy tính
Đối với Google Play Games trên máy tính, nền tảng này xử lý việc đổi kích thước cửa sổ trong khi vẫn tuân thủ tỷ lệ khung hình đã chỉ định. Kích thước cửa sổ được tự động khoá theo kích thước tối ưu. Bạn cần hỗ trợ tỷ lệ khung hình ít nhất là 16:9 nếu hướng chính là ngang và tỷ lệ khung hình 9:16 nếu trò chơi của bạn ở chế độ dọc. Để có trải nghiệm tốt nhất, hãy hỗ trợ rõ ràng các tỷ lệ khung hình 21:9, 16:10 và 3:2 cho trò chơi theo chiều ngang. Ở đây, bạn không bắt buộc phải đổi kích thước cửa sổ, nhưng vẫn có thể đổi kích thước để đảm bảo khả năng tương thích với các hệ số hình dạng khác.
Để biết thêm thông tin và các phương pháp hay nhất, hãy xem bài viết Định cấu hình đồ hoạ cho Google Play Games trên máy tính.
Màn hình lớn của ChromeOS và Android
Để tối đa hoá khu vực có thể xem của trò chơi ở chế độ toàn màn hình trên ChromeOS và thiết bị Android màn hình lớn, hãy hỗ trợ chế độ sống động toàn màn hình và ẩn các thanh hệ thống bằng cách thiết lập cờ trên decorView
, chế độ hiển thị giao diện người dùng hệ thống hoặc thông qua API WindowInsetsCompat
. Bạn cũng nên xử lý linh hoạt các sự kiện cấu hình xoay và đổi kích thước hoặc ngăn chúng xảy ra trên thiết bị ChromeOS.
Xin lưu ý rằng trên thiết bị Android có màn hình lớn, trò chơi của bạn có thể chạy ở các cấu hình mà có thể bạn chưa xử lý được. Nếu trò chơi của bạn không hỗ trợ tất cả các cấu hình kích thước cửa sổ và hướng, thì nền tảng sẽ tạo hiệu ứng hòm thư cho trò chơi ở chế độ tương thích và nếu cần, sẽ nhắc người chơi trước khi chuyển sang một cấu hình không được hỗ trợ.
Trên một số thiết bị, khi người chơi chuyển sang một cấu hình không được hỗ trợ, họ có thể được nhắc tải lại trò chơi và tạo lại hoạt động cho phù hợp nhất với bố cục cửa sổ mới. Điều này làm gián đoạn trải nghiệm chơi. Kiểm thử trò chơi của bạn ở nhiều cấu hình chế độ nhiều cửa sổ (kích thước cửa sổ 2/3, 1/2, 1/3) và xác minh không có phần tử lối chơi hoặc giao diện người dùng nào bị cắt hoặc không thể truy cập được. Ngoài ra, hãy kiểm thử cách trò chơi phản hồi tính liên tục của thiết bị có thể gập lại khi di chuyển giữa màn hình trong và màn hình ngoài trên thiết bị có thể gập lại. Nếu bạn gặp vấn đề, hãy xử lý rõ ràng các sự kiện cấu hình này và thêm tính năng hỗ trợ nâng cao cho khả năng đổi kích thước màn hình lớn.
Khả năng đổi kích thước màn hình lớn nâng cao
Để thoát khỏi chế độ tương thích và tránh tạo lại hoạt động, hãy làm như sau:
Khai báo hoạt động chính là có thể đổi kích thước:
<android:resizeableActivity="true" />
Khai báo khả năng hỗ trợ rõ ràng cho "Orientation", "screenSize", "smallestScreenSize", "screenLayout" và "Density" (mật độ) trong thuộc tính
android:configChanges
của phần tử<activity>
của tệp kê khai trò chơi để nhận tất cả sự kiện về cấu hình màn hình lớn:<android:configChanges="screenSize | smallestScreenSize | screenLayout | orientation | keyboard | keyboardHidden | density" />
Ghi đè
onConfigurationChanged()
và xử lý sự kiện cấu hình, bao gồm hướng, kích thước cửa sổ, chiều rộng và chiều cao hiện tại: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(); }
Bạn cũng có thể truy vấn WindowManager
để kiểm tra hướng xoay hiện tại của thiết bị. Bằng cách sử dụng siêu dữ liệu này, hãy kiểm tra các kích thước của cửa sổ mới và hiển thị ở kích thước cửa sổ đầy đủ. Tính năng này có thể không hoạt động trong mọi trường hợp do chênh lệch tỷ lệ khung hình. Vì vậy, hãy cố định giao diện người dùng của trò chơi vào kích thước cửa sổ mới và tạo khung viền hòm thư cho nội dung trò chơi cốt lõi của bạn. Nếu có hạn chế về kỹ thuật hoặc thiết kế ngăn cản phương pháp này, hãy thực hiện hiệu ứng hòm thư trong công cụ của riêng bạn để duy trì tỷ lệ khung hình và điều chỉnh tỷ lệ theo kích thước phù hợp nhất có thể trong khi khai báo resizeableActivity = false
và tránh chế độ cấu hình.
Bất kể bạn dùng phương pháp nào, hãy kiểm thử trò chơi ở nhiều cấu hình (gập và mở, thay đổi chế độ xoay khác nhau, chế độ chia đôi màn hình) và đảm bảo trò chơi không bị cắt hoặc chồng chéo các thành phần trên giao diện người dùng trong trò chơi, vấn đề về khả năng hỗ trợ tiếp cận đích chạm hoặc vấn đề về tỷ lệ khung hình khiến trò chơi bị kéo giãn, bị nén hoặc bị méo hình.
Ngoài ra, màn hình lớn hơn thường có nghĩa là pixel lớn hơn, vì bạn có cùng số lượng pixel cho một khu vực lớn hơn nhiều. Điều này có thể gây ra hiện tượng tạo pixel cho vùng đệm kết xuất giảm kích thước hoặc thành phần có độ phân giải thấp hơn. Hãy sử dụng các thành phần có chất lượng cao nhất trên thiết bị có màn hình lớn và hồ sơ hiệu suất của trò chơi để đảm bảo không có vấn đề gì. Nếu trò chơi của bạn hỗ trợ nhiều mức chất lượng, hãy đảm bảo trò chơi đó tính đến các thiết bị có màn hình lớn.
Chế độ nhiều cửa sổ
Chế độ nhiều cửa sổ cho phép nhiều ứng dụng đồng thời chia sẻ cùng một màn hình. Chế độ nhiều cửa sổ không thay đổi vòng đời hoạt động; tuy nhiên, trạng thái tiếp tục của ứng dụng trong chế độ nhiều cửa sổ sẽ khác nhau tuỳ theo phiên bản Android (xem phần Vòng đời hoạt động ở chế độ nhiều cửa sổ trong bài viết Hỗ trợ chế độ nhiều cửa sổ).
Khi người chơi đặt một ứng dụng hoặc trò chơi ở chế độ nhiều cửa sổ, hệ thống sẽ thông báo cho hoạt động về sự thay đổi đối với cấu hình, như được chỉ định trong phần Khả năng đổi kích thước nâng cao cho màn hình lớn. Việc thay đổi cấu hình cũng xảy ra khi người chơi đổi kích thước trò chơi hoặc đưa trò chơi trở lại chế độ toàn màn hình.
Không có gì đảm bảo rằng ứng dụng sẽ lấy lại tiêu điểm khi được đặt ở chế độ nhiều cửa sổ. Do đó, nếu bạn dùng bất kỳ sự kiện trạng thái ứng dụng nào để tạm dừng trò chơi, đừng dựa vào sự kiện thu nạp tâm điểm (onWindowFocusChanged()
có giá trị tâm điểm là true) để tiếp tục trò chơi. Thay vào đó, hãy dùng các trình xử lý sự kiện hoặc trình xử lý thay đổi trạng thái khác như onConfigurationChanged()
hoặc onResume()
. Xin lưu ý rằng bạn luôn có thể sử dụng phương thức isInMultiWindowMode()
để phát hiện xem hoạt động hiện tại có đang chạy ở chế độ nhiều cửa sổ hay không.
Với chế độ nhiều cửa sổ trên ChromeOS, kích thước cửa sổ ban đầu trở thành một yếu tố quan trọng cần cân nhắc. Trò chơi không nhất thiết phải ở chế độ toàn màn hình nhưng bạn cần khai báo kích thước của cửa sổ cho trường hợp đó. Chúng tôi có hai cách được đề xuất để xử lý vấn đề này.
Lựa chọn đầu tiên hoạt động bằng cách sử dụng các thuộc tính cụ thể trên thẻ <layout>
trong tệp kê khai Android của bạn. Thuộc tính defaultHeight
và defaultWidth
kiểm soát kích thước ban đầu. Ngoài ra, hãy lưu ý các thuộc tính minHeight
và minWidth
để ngăn người chơi thay đổi kích thước cửa sổ trò chơi thành những chiều mà bạn không hỗ trợ. Cuối cùng, có thuộc tính gravity
. Thuộc tính này giúp xác định vị trí mà cửa sổ xuất hiện trên màn hình khi khởi chạy. Dưới đây là một thẻ bố cục mẫu sử dụng các thuộc tính này:
<layout android:defaultHeight="500dp"
android:defaultWidth="600dp"
android:gravity="top|end"
android:minHeight="450dp"
android:minWidth="300dp" />
Lựa chọn thứ hai để đặt kích thước cửa sổ hoạt động thông qua việc sử dụng giới hạn khởi chạy động. Bằng cách sử dụng setLaunchBounds(Rect)
, bạn có thể xác định kích thước cửa sổ bắt đầu. Nếu bạn chỉ định một hình chữ nhật trống, thì hoạt động sẽ bắt đầu ở trạng thái tối đa.
Ngoài ra, nếu đang sử dụng công cụ phát triển trò chơi Unity hoặc Unreal, hãy đảm bảo bạn đang sử dụng phiên bản mới nhất (Unity 2019.4.40 và Unreal 5.3 trở lên) hỗ trợ tốt cho chế độ nhiều cửa sổ.
Hỗ trợ tư thế có thể gập lại
Sử dụng thư viện bố cục WindowManager của Jetpack để hỗ trợ các tư thế có thể gập lại (chẳng hạn như trên mặt bàn) để tăng mức độ tương tác và trải nghiệm của người chơi:
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); }