Przejście z telefonów na różne duże ekrany może wymagać przemyślenia, jak gra obsługuje zarządzanie oknami. W ChromeOS i Grach Google Play na PC gra może działać w trybie okna z głównym interfejsem pulpitu. Na nowych tabletach z Androidem i urządzeniach składanych z Androidem 12L (poziom interfejsu API 32) lub nowszym o szerokości ekranu > 600 dp, gra może działać równolegle w trybie podzielonego ekranu z innymi aplikacjami, zmieniać jej rozmiar, a nawet przenosić się między wewnętrznym a zewnętrznym ekranem na urządzeniach składanych, co prowadzi do zmiany konfiguracji rozmiaru okna, a na niektórych urządzeniach również orientacji.
Możliwość zmiany rozmiaru w grach na Unity
Podstawowa konfiguracja dużego ekranu
Określ, czy gra obsługuje możliwość zmiany rozmiaru:
<android:resizeableActivity="true" or "false" />
Jeśli nie możesz zmienić rozmiaru, sprawdź, czy w pliku manifestu gry są określone minimalne i maksymalne obsługiwane formaty obrazu:
<!-- 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">
Gry Google Play na PC
W przypadku Gier Google Play na PC platforma umożliwia zmianę rozmiaru okna z zachowaniem określonego współczynnika proporcji. Rozmiar okna jest automatycznie blokowany pod kątem optymalnych wymiarów. W przypadku gry w orientacji poziomej format obrazu musi wynosić co najmniej 16:9, a w trybie pionowym – 9:16. Aby uzyskać najlepsze wrażenia, musisz wyraźnie obsługiwać formaty 21:9, 16:10 i 3:2 w grach w orientacji poziomej. Zmiana rozmiaru okna nie jest w tym przypadku wymagana, ale warto ją włączyć w przypadku zgodności z innymi formatami.
Więcej informacji i sprawdzone metody znajdziesz w artykule Konfigurowanie grafiki w Grach Google Play na PC.
Duże ekrany ChromeOS i Androida
Aby zmaksymalizować widoczny obszar gry na pełnym ekranie na urządzeniach z ChromeOS i dużym ekranie, zapewnij obsługę trybu pełnoekranowego pełnoekranowego i ukryj paski systemowe. Aby to zrobić, ustaw flagi na decorView
, widoczność interfejsu systemu lub interfejs API WindowInsetsCompat
. Warto też bezproblemowo obsługiwać zdarzenia konfiguracji i zmieniać ich rozmiar oraz zapobiegać ich występowaniu na urządzeniach z ChromeOS.
Pamiętaj, że na dużych urządzeniach z Androidem gra może działać w konfiguracjach, z których być może jeszcze nie korzystasz. Jeśli gra nie obsługuje wszystkich konfiguracji rozmiaru i orientacji okna, platformy wyświetlają w niej tryb zgodności i w razie potrzeby poprosi o wprowadzenie nieobsługiwanej konfiguracji.
Na niektórych urządzeniach, gdy gracz przejdzie na nieobsługiwaną konfigurację, może zobaczyć prośbę o ponowne wczytanie gry i odtworzenie aktywności, aby jak najlepiej dopasować ją do nowego układu okna, co zakłóca rozgrywkę. Przetestuj grę w różnych konfiguracjach trybu wielu okien (2/3, 1/2 i 1/3 okna) i upewnij się, że żadna rozgrywka ani elementy interfejsu nie zostały ucięte lub niedostępne. Możesz też sprawdzić, jak Twoja gra reaguje na funkcję składanej ciągłości, gdy przechodzisz między ekranem wewnętrznym i zewnętrznym na urządzeniach składanych. Jeśli zauważysz problemy, musisz obsługiwać te zdarzenia konfiguracji i dodać zaawansowaną obsługę zmiany rozmiaru dużego ekranu.
Zaawansowana zmiana rozmiaru dużego ekranu
Aby wyjść z trybu zgodności i uniknąć odtwarzania aktywności, wykonaj te czynności:
Zadeklaruj główną aktywność jako z możliwością zmiany rozmiaru:
<android:resizeableActivity="true" />
Zadeklaruj wyraźną obsługę pól „orientation”, „screenSize”, „smallestScreenSize”, „screenLayout” i „gęstość” w atrybucie
android:configChanges
elementu<activity>
pliku manifestu gry, aby otrzymywać wszystkie zdarzenia konfiguracji dużego ekranu:<android:configChanges="screenSize | smallestScreenSize | screenLayout | orientation | keyboard | keyboardHidden | density" />
Zastąp
onConfigurationChanged()
i obsługuj zdarzenie konfiguracji, w tym bieżącą orientację, rozmiar okna, szerokość i wysokość: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(); }
Możesz też wysłać zapytanie do WindowManager
, aby sprawdzić bieżącą rotację urządzeń. Korzystając z tych metadanych, sprawdź wymiary nowego okna i wyrenderuj je do pełnego rozmiaru. Ze względu na różnice w formacie obrazu może to nie zadziałać we wszystkich przypadkach, dlatego możesz też zakotwiczyć interfejs gry w nowym rozmiarze okna i w czarnych pasach. Jeśli istnieją ograniczenia techniczne lub projektowe, które uniemożliwiają wprowadzenie którejś z tych opcji, utwórz własne czarne pasy w wyszukiwarce, aby zachować współczynnik proporcji, i przeskaluj do optymalnych wymiarów, zadeklarując resizeableActivity = false
i unikając trybu konfiguracji.
Niezależnie od wybranej metody przetestuj grę w różnych konfiguracjach (rozłożenie, różne zmiany obrotu, tryb podzielonego ekranu) i upewnij się, że nie ma żadnych przeciętych lub nakładających się elementów interfejsu w grze, problemów z dostępnością dotykiem lub z formatem obrazu, które powodują rozciągnięcie, zwarcie lub zniekształcenia w inny sposób.
Poza tym większe ekrany zwykle oznaczają większe piksele, bo ta sama liczba pikseli jest dużo większa. Może to powodować pikselizację w przypadku mniejszych buforów renderowania lub zasobów o niższej rozdzielczości. Na urządzeniach z dużym ekranem używaj zasobów najwyższej jakości i profiluj wydajność gry, aby uniknąć problemów. Jeśli gra obsługuje wiele poziomów jakości, sprawdź, czy obsługuje ona urządzenia z dużym ekranem.
Tryb wielu okien
Tryb wielu okien umożliwia jednoczesne korzystanie z tego samego ekranu wielu aplikacjom. Tryb wielu okien nie zmienia cyklu życia aktywności. jednak wznawianie aplikacji w wielu oknach różni się w zależności od wersji Androida (zobacz Cykl życia aktywności w trybie wielu okien w artykule Obsługa trybu wielu okien).
Gdy gracz przełącza aplikację lub grę w tryb wielu okien, system powiadamia o zmianie konfiguracji zgodnie z opisem w sekcji Zaawansowane zmiany rozmiaru dużego ekranu. Zmiana konfiguracji następuje też wtedy, gdy gracz zmienia rozmiar gry lub włącza ją z powrotem w tryb pełnego ekranu.
Nie ma gwarancji, że aplikacja ponownie się aktywuje po przejściu w tryb wielu okien. Dlatego jeśli do wstrzymania gry użyjesz dowolnego zdarzenia stanu aplikacji, nie korzystaj z zdarzenia polegającego na pozyskiwaniu ostrości (onWindowFocusChanged()
z wartością fokusem ustawionym na wartość true), aby wznowić grę. Zamiast nich używaj innych modułów obsługi zdarzeń lub modułów obsługi zmiany stanu, takich jak onConfigurationChanged()
lub onResume()
. Pamiętaj, że zawsze możesz użyć metody isInMultiWindowMode()
, aby wykryć, czy bieżąca aktywność działa w trybie wielu okien.
W trybie wielu okien w ChromeOS ważne są początkowe wymiary okien. Gra nie musi wyświetlać całego ekranu – w takim przypadku zadeklaruj wielkość okna. Możesz to zrobić na 2 sposoby.
Pierwsza opcja działa na podstawie określonych atrybutów w tagu <layout>
w pliku manifestu Androida. Atrybuty defaultHeight
i defaultWidth
określają wymiary początkowe. Pamiętaj też o atrybutach minHeight
i minWidth
, aby uniemożliwić graczom zmianę rozmiaru okna gry do wymiarów, których nie obsługujesz. Dostępny jest też atrybut gravity
, który określa, w którym miejscu na ekranie pojawi się okno po uruchomieniu. Oto przykładowy tag układu, który wykorzystuje te atrybuty:
<layout android:defaultHeight="500dp"
android:defaultWidth="600dp"
android:gravity="top|end"
android:minHeight="450dp"
android:minWidth="300dp" />
Druga opcja ustawiania rozmiaru okna działa przy użyciu dynamicznych granic uruchamiania. Za pomocą setLaunchBounds(Rect)
możesz zdefiniować wymiary okna początkowego. Jeśli wskażesz pusty prostokąt, aktywność będzie rozpoczęta w stanie zmaksymalizowanym.
Jeśli używasz silników gier Unity lub Unreal, sprawdź, czy używasz najnowszej wersji (Unity 2019.4.40 i Unreal 5.3 lub nowszej), która zapewnia prawidłową obsługę trybu wielu okien.
Obsługa składanego stanu
Użyj biblioteki układów WindowManager Jetpack do obsługi stanów składanych, na przykład stołu, aby zwiększyć zaangażowanie i zaangażowanie graczy.
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); }