Z tego dokumentu dowiesz się, jak skonfigurować i wyświetlać pakiet SDK Input w grach, które obsługują Gry Google Play na PC. Do zadań tych należy dodanie pakietu SDK do gry i wygenerowanie mapy danych wejściowych, która zawiera przypisania działań w grze do danych wejściowych użytkownika.
Zanim rozpoczniesz
Zanim dodasz pakiet SDK dotyczący danych wejściowych do gry, musisz obsługiwać dane wejściowe z klawiatury i myszy za pomocą systemu danych wejściowych silnika gry.
Pakiet SDK do obsługi wejścia przekazuje Google Play Games na PC informacje o sterowaniu w grze, aby można je wyświetlić użytkownikowi. Możesz też opcjonalnie zezwolić użytkownikom na zmianę mapowania klawiatury.
Każda kontrola to InputAction
(np. „J” oznacza „Jump” – „skok”), a Twoje InputActions
są zorganizowane w InputGroups
. InputGroup
może reprezentować inny tryb w grze, np. „Jazda”, „Chodzenie” lub „Menu główne”. Możesz też użyć InputContexts
, aby wskazać, które grupy są aktywne w różnych punktach gry.
Możesz włączyć automatyczne mapowanie klawiatury, ale jeśli wolisz mieć własny interfejs mapowania elementów sterujących, możesz wyłączyć mapowanie pakietu SDK wejścia.
Na poniższym diagramie sekwencji opisano, jak działa interfejs API pakietu Input SDK:
Gdy gra wdraża pakiet SDK dotyczący wprowadzania danych, elementy sterujące są wyświetlane w nakładce Gier Google Play na PC.
Warstwy Gier Google Play na PC
Nakładka Gier Google Play na PC („nakładka”) zawiera elementy sterujące zdefiniowane przez grę. Użytkownicy mogą w dowolnym momencie otworzyć nakładkę, naciskając Shift + Tab.
Sprawdzone metody projektowania przycisków skrótów
Podczas projektowania przycisków klawiatury należy wziąć pod uwagę te sprawdzone metody:
- Pogrupuj
InputActions
w logicznie powiązaneInputGroups
, aby ulepszyć nawigację i wykrywalność elementów sterujących podczas rozgrywki. - Każdy krok
InputGroup
może być przypisany do maksymalnie jednego krokuInputContext
. DokładneInputMap
zapewnia lepszą nawigację po elementach sterujących nakładki. - Utwórz
InputContext
dla każdego typu sceny w grze. Zwykle możesz użyć jednego taguInputContext
do wszystkich scen „podobnych do menu”. Używaj różnychInputContexts
w przypadku minigier w grze lub alternatywnych sterowań w pojedynczej scenie. - Jeśli 2 działania mają używać tego samego klucza w ramach tego samego
InputContext
, użyj ciągu etykiety, np. „Interakcja / Wywołanie”. - Jeśli 2 klucze mają być przypisane do tego samego
InputAction
, użyj 2 różnychInputActions
, które wykonują to samo działanie w grze. Możesz użyć tego samego ciągu etykiety dla obuInputActions
, ale ich identyfikatory muszą być różne. - Jeśli modyfikator jest stosowany do zestawu klawiszy, rozważ użycie pojedynczego klawisza
InputAction
z modyfikatorem zamiast wielu klawiszyInputAction
, które łączą modyfikator (np. użyj Shift i W, A, S, D zamiast Shift + W, Shift + A, Shift + S, Shift + D).InputActions
- Przemapowanie danych wejściowych jest automatycznie wyłączane, gdy użytkownik zacznie pisać w polach tekstowych. Postępuj zgodnie ze sprawdzonymi metodami implementowania pól tekstowych na Androidzie, aby zapewnić wykrywanie pól tekstowych w grze przez Androida i uniemożliwić zakłócanie im przez przypisane na nowo klawisze. Jeśli Twoja gra musi używać niekonwencjonalnych pól tekstowych, możesz użyć
setInputContext()
zInputContext
zawierającym pustą listęInputGroups
, aby ręcznie wyłączyć ponowne mapowanie. - Jeśli gra obsługuje przemapowanie, rozważ zaktualizowanie mapowania klawiszy. W miarę możliwości unikaj zmiany identyfikatorów istniejących elementów sterujących.
Funkcja przemapowania
Gry Google Play na PC obsługują przemapowanie sterowania za pomocą klawiatury na podstawie ustawień klawiszy udostępnianych przez grę za pomocą pakietu Input SDK. Jest to opcjonalne i można je całkowicie wyłączyć. Możesz na przykład udostępnić własny interfejs do ponownego mapowania klawiatury. Aby wyłączyć przemapowanie w grze, wystarczy określić opcję przemapowania jako wyłączoną dla InputMap
(więcej informacji znajdziesz w artykule Tworzenie mapy danych wejściowych).
Aby uzyskać dostęp do tej funkcji, użytkownicy muszą otworzyć nakładkę, a następnie kliknąć działanie, które chcą przemapować. Po każdym takim zdarzeniu Gry Google Play na PC mapują każde przemapowane przez użytkownika sterowanie na domyślne sterowanie, którego oczekuje gra. Dzięki temu gra nie musi wiedzieć o przemapowaniu przez gracza. Opcjonalnie możesz zaktualizować zasoby używane do wyświetlania elementów sterujących klawiaturą w grze, dodając wywołanie zwrotne do ponownego mapowania zdarzeń.
Gry Google Play na PC przechowują przypisane ponownie kontrolki lokalnie dla każdego użytkownika, co umożliwia zachowanie ustawień podczas kolejnych sesji gry. Te informacje są przechowywane na dysku tylko w przypadku platformy PC i nie mają wpływu na działanie aplikacji na urządzeniach mobilnych. Dane sterujące są usuwane, gdy użytkownik odinstaluje lub ponownie zainstaluje Gry Google Play na komputerze. Te dane nie są trwałe na wielu komputerach.
Aby umożliwić korzystanie z funkcji ponownego mapowania w grze, unikaj tych ograniczeń:
Ograniczenia dotyczące remapowania
Funkcja przypisywania klawiszy może zostać wyłączona w grze, jeśli przypisania klawiszy zawierają któryś z tych przypadków:
- Klucze wielokluczowe
InputActions
, które nie są złożone z klawisza modyfikującego i klawisza niemodyfikującego. Na przykład Shift + A jest prawidłową kombinacją, ale A + B, Ctrl + Alt czy Shift + A + Tab nie są prawidłowe. - Tag
InputMap
zawiera tagiInputActions
,InputGroups
lubInputContexts
z powtarzającymi się unikalnym identyfikatorami.
Ograniczenia mapowania
Podczas projektowania przycisków do ponownego mapowania weź pod uwagę te ograniczenia:
- Przypisywanie nowych funkcji do kombinacji klawiszy nie jest obsługiwane. Użytkownicy nie mogą na przykład zmienić skrótu Shift + A na Ctrl + B ani A na Shift + A.
- Przypisanie nowych funkcji do przycisków
InputActions
myszy nie jest obsługiwane. Na przykład skrót Shift + prawy przycisk myszy nie może zostać zmieniony.
Testowanie zmiany mapowania klawiszy w emulatorze Gier Google Play na PC
Funkcję przemapowania w Gry Google Play na emulatorze PC można włączyć w dowolnym momencie, podając ten sam komendę adb:
adb shell dumpsys input_mapping_service --set RemappingFlagValue true
Zmiana nakładki jak na poniższym obrazie:
Dodawanie pakietu SDK
Zainstaluj pakiet Input SDK na odpowiedniej platformie programistycznej.
Java i Kotlin
Pobierz pakiet SDK do obsługi danych wejściowych na potrzeby języka Java lub Kotlin, dodając zależność do pliku build.gradle
na poziomie modułu:
dependencies {
implementation 'com.google.android.libraries.play.games:inputmapping:1.1.1-beta'
...
}
Unity
Pakiet SDK do obsługi danych wejściowych to standardowy pakiet Unity z kilkoma zależnościami.
Wymagane jest zainstalowanie pakietu ze wszystkimi zależnościami. Pakiety można instalować na kilka sposobów.
Zainstaluj aplikację .unitypackage
.
Pobierz plik pakietu SDK do wprowadzania danych w formacie unitypackage ze wszystkimi zależnościami. Aby zainstalować .unitypackage
, wybierz Zasoby > Importuj pakiet > Własny pakiet i wskaż pobrany plik.
Instalowanie za pomocą UPM
Możesz też zainstalować pakiet za pomocą menedżera pakietów Unity, pobierając pakiet .tgz
i instalując jego zależności:
- com.google.external-dependency-manager-1.2.172
- com.google.librarywrapper.java-0.2.0
- com.google.librarywrapper.openjdk8-0.2.0
- com.google.android.libraries.play.games.inputmapping-1.1.1-beta (lub wybranie pliku tgz z tego archiwum).
Instalowanie za pomocą OpenUPM
Pakiet możesz zainstalować za pomocą OpenUPM.
$ openupm add com.google.android.libraries.play.games.inputmapping
Przykładowe gry
Przykłady integracji z pakietem SDK do obsługi danych wejściowych znajdziesz w przypadku gier w językach Kotlin i Java (AGDK Tunnel) oraz gier w Unity (Trivial Kart).
Generowanie ustawień klawiszy
Zarejestruj przypisania klawiszy, tworząc InputMap
i zwracając je za pomocą funkcji InputMappingProvider
. Ten przykład przedstawia:InputMappingProvider
Kotlin
class InputSDKProvider : InputMappingProvider { override fun onProvideInputMap(): InputMap { TODO("Not yet implemented") } }
Java
public class InputSDKProvider implements InputMappingProvider { private static final String INPUTMAP_VERSION = "1.0.0"; @Override @NonNull public InputMap onProvideInputMap() { // TODO: return an InputMap } }
C#
#if PLAY_GAMES_PC using Java.Lang; using Java.Util; using Google.Android.Libraries.Play.Games.Inputmapping; using Google.Android.Libraries.Play.Games.Inputmapping.Datamodel; public class InputSDKProvider : InputMappingProviderCallbackHelper { public static readonly string INPUT_MAP_VERSION = "1.0.0"; public override InputMap OnProvideInputMap() { // TODO: return an InputMap } } #endif
Definiowanie działań wejściowych
Klasa InputAction
służy do mapowania klawisza lub kombinacji klawiszy na działanie w grze. InputActions
muszą mieć unikalne identyfikatory we wszystkich InputActions
.
Jeśli obsługujesz mapowanie, możesz określić, jakie InputActions
można przemapować. Jeśli gra nie obsługuje przemapowania, opcję przemapowania należy wyłączyć we wszystkich InputActions
, ale Input SDK jest na tyle inteligentny, że wyłączy przemapowanie, jeśli nie obsługuje go InputMap
.
W tym przykładzie klawisz
Kotlin
companion object { private val driveInputAction = InputAction.create( "Drive", InputActionsIds.DRIVE.ordinal.toLong(), InputControls.create(listOf(KeyEvent.KEYCODE_SPACE), emptyList()), InputEnums.REMAP_OPTION_ENABLED) }
Java
private static final InputAction driveInputAction = InputAction.create( "Drive", InputEventIds.DRIVE.ordinal(), InputControls.create( Collections.singletonList(KeyEvent.KEYCODE_SPACE), Collections.emptyList()), InputEnums.REMAP_OPTION_ENABLED );
C#
private static readonly InputAction driveInputAction = InputAction.Create( "Drive", (long)InputEventIds.DRIVE, InputControls.Create( new[] { new Integer(AndroidKeyCode.KEYCODE_SPACE) }.ToJavaList(), new ArrayList<Integer>()), InputEnums.REMAP_OPTION_ENABLED );
Działania mogą też obejmować dane wejściowe z myszy. W tym przykładzie kliknięcie lewym przyciskiem myszy jest przypisane do działania Przenieś:
Kotlin
companion object { private val mouseInputAction = InputAction.create( "Move", InputActionsIds.MOUSE_MOVEMENT.ordinal.toLong(), InputControls.create(emptyList(), listOf(InputControls.MOUSE_LEFT_CLICK)), InputEnums.REMAP_OPTION_DISABLED) }
Java
private static final InputAction mouseInputAction = InputAction.create( "Move", InputActionsIds.MOUSE_MOVEMENT.ordinal(), InputControls.create( Collections.emptyList(), Collections.singletonList(InputControls.MOUSE_LEFT_CLICK) ), InputEnums.REMAP_OPTION_DISABLED );
C#
private static readonly InputAction mouseInputAction = InputAction.Create( "Move", (long)InputEventIds.MOUSE_MOVEMENT, InputControls.Create( new ArrayList<Integer>(), new[] { new Integer((int)PlayMouseAction.MouseLeftClick) }.ToJavaList() ), InputEnums.REMAP_OPTION_DISABLED );
Kombinacje klawiszy są określane przez przekazanie wielu kodów klawiszy do funkcji InputAction
. W tym przykładzie
Kotlin
companion object { private val turboInputAction = InputAction.create( "Turbo", InputActionsIds.TURBO.ordinal.toLong(), InputControls.create( listOf(KeyEvent.KEYCODE_SHIFT_LEFT, KeyEvent.KEYCODE_SPACE), emptyList()), InputEnums.REMAP_OPTION_ENABLED) }
Java
private static final InputAction turboInputAction = InputAction.create( "Turbo", InputActionsIds.TURBO.ordinal(), InputControls.create( Arrays.asList(KeyEvent.KEYCODE_SHIFT_LEFT, KeyEvent.KEYCODE_SPACE), Collections.emptyList() ), InputEnums.REMAP_OPTION_ENABLED );
C#
private static readonly InputAction turboInputAction = InputAction.Create( "Turbo", (long)InputEventIds.TURBO, InputControls.Create( new[] { new Integer(AndroidKeyCode.KEYCODE_SHIFT_LEFT), new Integer(AndroidKeyCode.KEYCODE_SPACE) }.ToJavaList(), new ArrayList<Integer>()), InputEnums.REMAP_OPTION_ENABLED );
Pakiet SDK wejścia umożliwia łączenie przycisków myszy i klawiszy w jednym działaniu. Ten przykład pokazuje, że naciśnięcie
Kotlin
companion object { private val addWaypointInputAction = InputAction.create( "Add waypoint", InputActionsIds.ADD_WAYPOINT.ordinal.toLong(), InputControls.create( listOf(KeyEvent.KeyEvent.KEYCODE_TAB), listOf(InputControls.MOUSE_RIGHT_CLICK)), InputEnums.REMAP_OPTION_DISABLED) }
Java
private static final InputAction addWaypointInputAction = InputAction.create( "Add waypoint", InputActionsIds.ADD_WAYPOINT.ordinal(), InputControls.create( Collections.singletonList(KeyEvent.KEYCODE_TAB), Collections.singletonList(InputControls.MOUSE_RIGHT_CLICK) ), InputEnums.REMAP_OPTION_DISABLED );
C#
private static readonly InputAction addWaypointInputAction = InputAction.Create( "Add waypoint", (long)InputEventIds.ADD_WAYPOINT, InputControls.Create( new[] { new Integer(AndroidKeyCode.KEYCODE_SPACE) }.ToJavaList(), new[] { new Integer((int)PlayMouseAction.MouseRightClick) }.ToJavaList() ), InputEnums.REMAP_OPTION_DISABLED );
Pole InputAction zawiera te pola:
ActionLabel
: ciąg tekstowy wyświetlany w interfejsie, który reprezentuje to działanie. Lokalizacja nie jest wykonywana automatycznie, dlatego należy ją przeprowadzić na wczesnym etapie.InputControls
: definiuje elementy sterujące, których używa to działanie. Kontroluje mapę, aby uzyskać spójne glify na nakładce.InputActionId
: obiektInputIdentifier
, który przechowuje numer identyfikacyjny i wersjęInputAction
(więcej informacji znajdziesz w sekcji Identyfikatory kluczy śledzenia).InputRemappingOption
: należy doInputEnums.REMAP_OPTION_ENABLED
lubInputEnums.REMAP_OPTION_DISABLED
. Określa, czy działanie jest włączone do przemapowania. Jeśli gra nie obsługuje przemapowania, możesz pominąć to pole lub po prostu je wyłączyć.RemappedInputControls
: obiektInputControls
tylko do odczytu, który służy do odczytywania przemapowanego klucza ustawionego przez użytkownika w przypadku zdarzeń przemapowania (używany do otrzymywania powiadomień o zdarzeniach przemapowania).
InputControls
reprezentuje dane wejściowe powiązane z działaniem i zawiera te pola:
AndroidKeycodes
: lista liczb całkowitych reprezentujących naciśnięcia klawiszy powiązane z działaniem. Są one zdefiniowane w klasie KeyEvent lub w klasie AndroidKeycode w Unity.MouseActions
: lista wartościMouseAction
reprezentujących sygnały myszy powiązane z tym działaniem.
Definiowanie grup danych wejściowych
InputActions
są grupowane z powiązanymi logicznie działaniami za pomocą InputGroups
, aby ułatwić nawigację i odkrywanie elementów sterujących w nakładce. Każdy identyfikator InputGroup
musi być niepowtarzalny w przypadku wszystkich InputGroups
w grze.
Dzięki grupowaniu działań związanych z wprowadzaniem danych ułatwiasz graczom znajdowanie odpowiedniego przypisania klawiszy w bieżącym kontekście.
Jeśli obsługujesz mapowanie, możesz określić, jakie InputGroups
można przemapować. Jeśli gra nie obsługuje przemapowania, opcję przemapowania należy wyłączyć we wszystkich InputGroups
, ale Input SDK jest na tyle inteligentny, że wyłączy przemapowanie, jeśli nie obsługuje go InputMap
.
Kotlin
companion object { private val menuInputGroup = InputGroup.create( "Menu keys", listOf( navigateUpInputAction, navigateLeftInputAction, navigateDownInputAction, navigateRightInputAction, openMenuInputAction, returnMenuInputAction), InputGroupsIds.MENU_ACTION_KEYS.ordinal.toLong(), InputEnums.REMAP_OPTION_ENABLED ) }
Java
private static final InputGroup menuInputGroup = InputGroup.create( "Menu keys", Arrays.asList( navigateUpInputAction, navigateLeftInputAction, navigateDownInputAction, navigateRightInputAction, openMenuInputAction, returnMenuInputAction), InputGroupsIds.MENU_ACTION_KEYS.ordinal(), REMAP_OPTION_ENABLED );
C#
private static readonly InputGroup menuInputGroup = InputGroup.Create( "Menu keys", new[] { navigateUpInputAction, navigateLeftInputAction, navigateDownInputAction, navigateRightInputAction, openMenuInputAction, returnMenuInputAction, }.ToJavaList(), (long)InputGroupsIds.MENU_ACTION_KEYS, InputEnums.REMAP_OPTION_ENABLED );
W tym przykładzie na nakładce widać grupy elementów sterujących Droga i Menu:
InputGroup
zawiera te pola:
GroupLabel
: ciąg znaków wyświetlany w nakładce, który może służyć do logicznego grupowania zestawu działań. Ten ciąg nie jest automatycznie lokalizowany.InputActions
: lista obiektówInputAction
zdefiniowanych w poprzednim kroku. Wszystkie te działania są wizualnie wyświetlane pod nagłówkiem grupy.InputGroupId
: obiektInputIdentifier
, który przechowuje identyfikator numeru i wersjęInputGroup
. Więcej informacji znajdziesz w artykule Identyfikatory kluczy śledzenia.InputRemappingOption
:InputEnums.REMAP_OPTION_ENABLED
lubInputEnums.REMAP_OPTION_DISABLED
. Jeśli ta opcja jest wyłączona, przemapowanie jest wyłączone dla wszystkich obiektówInputAction
należących do tej grupy, nawet jeśli opcja przemapowania jest włączona. Jeśli ta opcja jest włączona, wszystkie działania należące do tej grupy mogą być przemapowane, chyba że zostały wyłączone w przypadku poszczególnych działań.
Definiowanie kontekstów danych wejściowych
InputContexts
pozwala grze używać innego zestawu elementów sterujących na klawiaturze w różnych scenach. Przykład:
- Możesz używać różnych zestawów danych wejściowych do poruszania się po menu i do poruszania się w grze.
- Możesz określić różne zestawy danych wejściowych w zależności od trybu poruszania się w grze, np. jazdy lub chodzenia.
- Możesz określić różne zestawy danych wejściowych na podstawie bieżącego stanu gry, np. nawigacji po świecie gry lub rozgrywki na poszczególnych poziomach.
Gdy używasz InputContexts
, nakładka pokazuje najpierw grupy kontekstu, Aby włączyć to zachowanie, wywołaj funkcję setInputContext()
, aby ustawić kontekst za każdym razem, gdy gra przechodzi do innej sceny. Na poniższym obrazie widać, jak to działa: w scenie „prowadzenie pojazdu” u góry nakładki wyświetlane są działania sterowania ruchem drogowym. Po otwarciu menu „sklep” u góry nakładki wyświetlają się działania „elementów sterujących menu”.
Te aktualizacje nakładki są osiągane przez ustawienie innego InputContext
w różnych punktach gry. Aby to zrobić:
- Grupuj
InputActions
z logicznie powiązanymi działaniami za pomocąInputGroups
- Przypisz te
InputGroups
doInputContext
w różnych częściach gry.
InputGroups
należące do tego samegoInputContext
nie mogą mieć sprzecznychInputActions
, w których używany jest ten sam klucz. Dobrą praktyką jest przypisywanie każdego elementu InputGroup
do jednego elementu InputContext
.
Poniższy przykładowy kod demonstruje logikę InputContext
:
Kotlin
companion object { val menuSceneInputContext = InputContext.create( "Menu", InputIdentifier.create( INPUTMAP_VERSION, InputContextIds.MENU_SCENE.ordinal.toLong()), listOf(basicMenuNavigationInputGroup, menuActionsInputGroup)) val gameSceneInputContext = InputContext.create( "Game", InputIdentifier.create( INPUTMAP_VERSION, InputContextIds.GAME_SCENE.ordinal.toLong()), listOf( movementInputGroup, mouseActionsInputGroup, emojisInputGroup, gameActionsInputGroup)) }
Java
public static final InputContext menuSceneInputContext = InputContext.create( "Menu", InputIdentifier.create( INPUTMAP_VERSION, InputContextIds.MENU_SCENE.ordinal()), Arrays.asList( basicMenuNavigationInputGroup, menuActionsInputGroup ) ); public static final InputContext gameSceneInputContext = InputContext.create( "Game", InputIdentifier.create( INPUTMAP_VERSION, InputContextIds.GAME_SCENE.ordinal()), Arrays.asList( movementInputGroup, mouseActionsInputGroup, emojisInputGroup, gameActionsInputGroup ) );
C#
public static readonly InputContext menuSceneInputContext = InputContext.Create( "Menu", InputIdentifier.Create( INPUT_MAP_VERSION, (long)InputContextsIds.MENU_SCENE), new[] { basicMenuNavigationInputGroup, menuActionsInputGroup }.ToJavaList() ); public static readonly InputContext gameSceneInputContext = InputContext.Create( "Game", InputIdentifier.Create( INPUT_MAP_VERSION, (long)InputContextsIds.GAME_SCENE), new[] { movementInputGroup, mouseActionsInputGroup, emojisInputGroup, gameActionsInputGroup }.ToJavaList() );
InputContext
zawiera te pola:
LocalizedContextLabel
: ciąg znaków opisujący grupy należące do kontekstu.InputContextId
: obiektInputIdentifier
, który przechowuje numer identyfikacyjny i wersjęInputContext
(więcej informacji znajdziesz w sekcji Identyfikatory kluczy śledzenia).ActiveGroups
: listaInputGroups
, które mają być używane i wyświetlane u góry nakładki, gdy ten kontekst jest aktywny.
Tworzenie mapy danych wejściowych
InputMap
to zbiór wszystkich obiektów InputGroup
dostępnych w grze, a zatem wszystkich obiektów InputAction
, których działania może oczekiwać gracz.
Gdy zgłaszasz przypisania klawiszy, tworzysz InputMap
ze wszystkimi
InputGroups
używanymi w grze.
Jeśli gra nie obsługuje przypisywania, wyłącz opcję przypisywania, a zarezerwowane klawisze pozostaw puste.
W tym przykładzie tworzymy element InputMap
, który służy do raportowania zbioru elementów InputGroups
.
Kotlin
companion object { val gameInputMap = InputMap.create( listOf( basicMenuNavigationInputGroup, menuActionKeysInputGroup, movementInputGroup, mouseMovementInputGroup, pauseMenuInputGroup), MouseSettings.create(true, false), InputIdentifier.create(INPUTMAP_VERSION, INPUT_MAP_ID.toLong()), InputEnums.REMAP_OPTION_ENABLED, // Use ESCAPE as reserved remapping key listof(InputControls.create(listOf(KeyEvent.KEYCODE_ESCAPE), emptyList())) ) }
Java
public static final InputMap gameInputMap = InputMap.create( Arrays.asList( basicMenuNavigationInputGroup, menuActionKeysInputGroup, movementInputGroup, mouseMovementInputGroup, pauseMenuInputGroup), MouseSettings.create(true, false), InputIdentifier.create(INPUTMAP_VERSION, INPUT_MAP_ID), REMAP_OPTION_ENABLED, // Use ESCAPE as reserved remapping key Arrays.asList( InputControls.create( Collections.singletonList(KeyEvent.KEYCODE_ESCAPE), Collections.emptyList() ) ) );
C#
public static readonly InputMap gameInputMap = InputMap.Create( new[] { basicMenuNavigationInputGroup, menuActionKeysInputGroup, movementInputGroup, mouseMovementInputGroup, pauseMenuInputGroup, }.ToJavaList(), MouseSettings.Create(true, false), InputIdentifier.Create(INPUT_MAP_VERSION, INPUT_MAP_ID), InputEnums.REMAP_OPTION_ENABLED, // Use ESCAPE as reserved remapping key new[] { InputControls.Create( New[] { new Integer(AndroidKeyCode.KEYCODE_ESCAPE) }.ToJavaList(), new ArrayList<Integer>()) }.ToJavaList() );
InputMap
zawiera te pola:
InputGroups
: grupy danych InputGroups z Twojej gry. Grupy są wyświetlane w kolejności w nakładce, chyba że określisz aktualne grupy w używanych wywołaniachsetInputContext()
.MouseSettings
: obiektMouseSettings
wskazuje, że czułość myszy można dostosować, a mysz jest odwrócona na osi y.InputMapId
: obiektInputIdentifier
, który przechowuje numer identyfikacyjny i wersjęInputMap
(więcej informacji znajdziesz w sekcji Identyfikatory kluczy śledzenia).InputRemappingOption
:InputEnums.REMAP_OPTION_ENABLED
lubInputEnums.REMAP_OPTION_DISABLED
. Określa, czy funkcja przemapowania jest włączona.ReservedControls
: listaInputControls
, których użytkownicy nie będą mogli przemapować.
Śledź identyfikatory kluczy
Obiekty InputAction
, InputGroup
, InputContext
i InputMap
zawierają obiekt InputIdentifier
, który przechowuje unikalny identyfikator liczbowy i identyfikator wersji w postaci ciągu znaków.
Śledzenie wersji ciągu znaków w obiektach jest opcjonalne, ale zalecane, aby śledzić wersje InputMap
. Jeśli nie podasz wersji ciągu znaków, będzie on pusty. W przypadku obiektów InputMap
wymagana jest wersja ciągu znaków.
W tym przykładzie wersja ciągu znaków jest przypisywana do InputActions
lub InputGroups
:
Kotlin
class InputSDKProviderKotlin : InputMappingProvider { companion object { const val INPUTMAP_VERSION = "1.0.0" private val enterMenuInputAction = InputAction.create( "Enter menu", InputControls.create(listOf(KeyEvent.KEYCODE_ENTER), emptyList()), InputIdentifier.create( INPUTMAP_VERSION, InputActionsIds.ENTER_MENU.ordinal.toLong()), InputEnums.REMAP_OPTION_ENABLED ) private val movementInputGroup = InputGroup.create( "Basic movement", listOf( moveUpInputAction, moveLeftInputAction, moveDownInputAction, mouseGameInputAction), InputIdentifier.create( INPUTMAP_VERSION, InputGroupsIds.BASIC_MOVEMENT.ordinal.toLong()), InputEnums.REMAP_OPTION_ENABLED) } }
Java
public class InputSDKProvider implements InputMappingProvider { public static final String INPUTMAP_VERSION = "1.0.0"; private static final InputAction enterMenuInputAction = InputAction.create( "Enter menu", InputControls.create( Collections.singletonList(KeyEvent.KEYCODE_ENTER), Collections.emptyList()), InputIdentifier.create( INPUTMAP_VERSION, InputActionsIds.ENTER_MENU.ordinal()), InputEnums.REMAP_OPTION_ENABLED ); private static final InputGroup movementInputGroup = InputGroup.create( "Basic movement", Arrays.asList( moveUpInputAction, moveLeftInputAction, moveDownInputAction, moveRightInputAction, mouseGameInputAction ), InputIdentifier.create( INPUTMAP_VERSION, InputGroupsIds.BASIC_MOVEMENT.ordinal()), InputEnums.REMAP_OPTION_ENABLED ); }
C#
#if PLAY_GAMES_PC using Java.Lang; using Java.Util; using Google.Android.Libraries.Play.Games.Inputmapping; using Google.Android.Libraries.Play.Games.Inputmapping.Datamodel; public class InputSDKMappingProvider : InputMappingProviderCallbackHelper { public static readonly string INPUT_MAP_VERSION = "1.0.0"; private static readonly InputAction enterMenuInputAction = InputAction.Create( "Enter menu", InputControls.Create( new[] { new Integer(AndroidKeyCode.KEYCODE_SPACE)}.ToJavaList(), new ArrayList<Integer>()), InputIdentifier.Create( INPUT_MAP_VERSION, (long)InputEventIds.ENTER_MENU), InputEnums.REMAP_OPTION_ENABLED ); private static readonly InputGroup movementInputGroup = InputGroup.Create( "Basic movement", new[] { moveUpInputAction, moveLeftInputAction, moveDownInputAction, moveRightInputAction, mouseGameInputAction }.ToJavaList(), InputIdentifier.Create( INPUT_MAP_VERSION, (long)InputGroupsIds.BASIC_MOVEMENT), InputEnums.REMAP_OPTION_ENABLED ); } #endif
Numery identyfikacyjne obiektów InputAction
muszą być unikalne wśród wszystkich InputActions
na Twoim koncie InputMap
. Podobnie identyfikatory obiektów InputGroup
muszą być unikalne w przypadku wszystkich InputGroups
w InputMap
. Ten przykład pokazuje, jak za pomocą tagu enum
śledzić unikalne identyfikatory obiektów:
Kotlin
enum class InputActionsIds { NAVIGATE_UP, NAVIGATE_DOWN, ENTER_MENU, EXIT_MENU, // ... JUMP, RUN, EMOJI_1, EMOJI_2, // ... } enum class InputGroupsIds { // Main menu scene BASIC_NAVIGATION, // WASD, Enter, Backspace MENU_ACTIONS, // C: chat, Space: quick game, S: store // Gameplay scene BASIC_MOVEMENT, // WASD, space: jump, Shift: run MOUSE_ACTIONS, // Left click: shoot, Right click: aim EMOJIS, // Emojis with keys 1,2,3,4 and 5 GAME_ACTIONS, // M: map, P: pause, R: reload } enum class InputContextIds { MENU_SCENE, // Basic menu navigation, menu actions GAME_SCENE, // Basic movement, mouse actions, emojis, game actions } const val INPUT_MAP_ID = 0
Java
public enum InputActionsIds { NAVIGATE_UP, NAVIGATE_DOWN, ENTER_MENU, EXIT_MENU, // ... JUMP, RUN, EMOJI_1, EMOJI_2, // ... } public enum InputGroupsIds { // Main menu scene BASIC_NAVIGATION, // WASD, Enter, Backspace MENU_ACTIONS, // C: chat, Space: quick game, S: store // Gameplay scene BASIC_MOVEMENT, // WASD, space: jump, Shift: run MOUSE_ACTIONS, // Left click: shoot, Right click: aim EMOJIS, // Emojis with keys 1,2,3,4 and 5 GAME_ACTIONS, // M: map, P: pause, R: reload } public enum InputContextIds { MENU_SCENE, // Basic navigation, menu actions GAME_SCENE, // Basic movement, mouse actions, emojis, game actions } public static final long INPUT_MAP_ID = 0;
C#
public enum InputActionsIds { NAVIGATE_UP, NAVIGATE_DOWN, ENTER_MENU, EXIT_MENU, // ... JUMP, RUN, EMOJI_1, EMOJI_2, // ... } public enum InputGroupsIds { // Main menu scene BASIC_NAVIGATION, // WASD, Enter, Backspace MENU_ACTIONS, // C: chat, Space: quick game, S: store // Gameplay scene BASIC_MOVEMENT, // WASD, space: jump, Shift: run MOUSE_ACTIONS, // Left click: shoot, Right click: aim EMOJIS, // Emojis with keys 1,2,3,4 and 5 GAME_ACTIONS, // M: map, P: pause, R: reload } public enum InputContextIds { MENU_SCENE, // Basic navigation, menu actions GAME_SCENE, // Basic movement, mouse actions, emojis, game actions } public static readonly long INPUT_MAP_ID = 0;
InputIdentifier
zawiera te pola:
UniqueId
: unikalny identyfikator liczbowy, który jednoznacznie identyfikuje dany zestaw danych wejściowych.VersionString
: czytelny dla człowieka ciąg znaków określający wersję danych wejściowych między 2 wersjami zmian danych wejściowych.
otrzymywać powiadomienia o przemapowaniu zdarzeń (opcjonalnie),
otrzymywać powiadomienia o przypisanych wydarzeniach, aby wiedzieć, które klawisze są używane w grze; Dzięki temu gra może aktualizować zasoby wyświetlane na ekranie gry, które służą do wyświetlania elementów sterujących.
Na poniższym obrazku widać przykład tego zachowania: po przemapowaniu klawiszy
Ta funkcja jest realizowana przez zarejestrowanie wywołania zwrotnego InputRemappingListener
. Aby wdrożyć tę funkcję, zacznij od zarejestrowania wystąpienia InputRemappingListener
:
Kotlin
class InputSDKRemappingListener : InputRemappingListener { override fun onInputMapChanged(inputMap: InputMap) { Log.i(TAG, "Received update on input map changed.") if (inputMap.inputRemappingOption() == InputEnums.REMAP_OPTION_DISABLED) { return } for (inputGroup in inputMap.inputGroups()) { if (inputGroup.inputRemappingOption() == InputEnums.REMAP_OPTION_DISABLED) { continue } for (inputAction in inputGroup.inputActions()) { if (inputAction.inputRemappingOption() != InputEnums.REMAP_OPTION_DISABLED) { // Found InputAction remapped by user processRemappedAction(inputAction) } } } } private fun processRemappedAction(remappedInputAction: InputAction) { // Get remapped action info val remappedControls = remappedInputAction.remappedInputControls() val remappedKeyCodes = remappedControls.keycodes() val mouseActions = remappedControls.mouseActions() val version = remappedInputAction.inputActionId().versionString() val remappedActionId = remappedInputAction.inputActionId().uniqueId() val currentInputAction: Optional<InputAction> currentInputAction = if (version == null || version.isEmpty() || version == InputSDKProvider.INPUTMAP_VERSION ) { getCurrentVersionInputAction(remappedActionId) } else { Log.i(TAG, "Detected version of user-saved input action defers from current version") getCurrentVersionInputActionFromPreviousVersion( remappedActionId, version) } if (!currentInputAction.isPresent) { Log.e(TAG, String.format( "can't find remapped input action with id %d and version %s", remappedActionId, if (version == null || version.isEmpty()) "UNKNOWN" else version)) return } val originalControls = currentInputAction.get().inputControls() val originalKeyCodes = originalControls.keycodes() Log.i(TAG, String.format( "Found input action with id %d remapped from key %s to key %s", remappedActionId, keyCodesToString(originalKeyCodes), keyCodesToString(remappedKeyCodes))) // TODO: make display changes to match controls used by the user } private fun getCurrentVersionInputAction(inputActionId: Long): Optional<InputAction> { for (inputGroup in InputSDKProvider.gameInputMap.inputGroups()) { for (inputAction in inputGroup.inputActions()) { if (inputAction.inputActionId().uniqueId() == inputActionId) { return Optional.of(inputAction) } } } return Optional.empty() } private fun getCurrentVersionInputActionFromPreviousVersion( inputActionId: Long, previousVersion: String ): Optional<InputAction7gt; { // TODO: add logic to this method considering the diff between the current and previous // InputMap. return Optional.empty() } private fun keyCodesToString(keyCodes: List<Int>): String { val builder = StringBuilder() for (keyCode in keyCodes) { if (!builder.toString().isEmpty()) { builder.append(" + ") } builder.append(keyCode) } return String.format("(%s)", builder) } companion object { private const val TAG = "InputSDKRemappingListener" } }
Java
public class InputSDKRemappingListener implements InputRemappingListener { private static final String TAG = "InputSDKRemappingListener"; @Override public void onInputMapChanged(InputMap inputMap) { Log.i(TAG, "Received update on input map changed."); if (inputMap.inputRemappingOption() == InputEnums.REMAP_OPTION_DISABLED) { return; } for (InputGroup inputGroup : inputMap.inputGroups()) { if (inputGroup.inputRemappingOption() == InputEnums.REMAP_OPTION_DISABLED) { continue; } for (InputAction inputAction : inputGroup.inputActions()) { if (inputAction.inputRemappingOption() != InputEnums.REMAP_OPTION_DISABLED) { // Found InputAction remapped by user processRemappedAction(inputAction); } } } } private void processRemappedAction(InputAction remappedInputAction) { // Get remapped action info InputControls remappedControls = remappedInputAction.remappedInputControls(); List<Integer> remappedKeyCodes = remappedControls.keycodes(); List<Integer> mouseActions = remappedControls.mouseActions(); String version = remappedInputAction.inputActionId().versionString(); long remappedActionId = remappedInputAction.inputActionId().uniqueId(); Optional<InputAction> currentInputAction; if (version == null || version.isEmpty() || version.equals(InputSDKProvider.INPUTMAP_VERSION)) { currentInputAction = getCurrentVersionInputAction(remappedActionId); } else { Log.i(TAG, "Detected version of user-saved input action defers " + "from current version"); currentInputAction = getCurrentVersionInputActionFromPreviousVersion( remappedActionId, version); } if (!currentInputAction.isPresent()) { Log.e(TAG, String.format( "input action with id %d and version %s not found", remappedActionId, version == null || version.isEmpty() ? "UNKNOWN" : version)); return; } InputControls originalControls = currentInputAction.get().inputControls(); List<Integer> originalKeyCodes = originalControls.keycodes(); Log.i(TAG, String.format( "Found input action with id %d remapped from key %s to key %s", remappedActionId, keyCodesToString(originalKeyCodes), keyCodesToString(remappedKeyCodes))); // TODO: make display changes to match controls used by the user } private Optional<InputAction> getCurrentVersionInputAction( long inputActionId) { for (InputGroup inputGroup : InputSDKProvider.gameInputMap.inputGroups()) { for (InputAction inputAction : inputGroup.inputActions()) { if (inputAction.inputActionId().uniqueId() == inputActionId) { return Optional.of(inputAction); } } } return Optional.empty(); } private Optional<InputAction> getCurrentVersionInputActionFromPreviousVersion( long inputActionId, String previousVersion) { // TODO: add logic to this method considering the diff between your // current and previous InputMap. return Optional.empty(); } private String keyCodesToString(List<Integer> keyCodes) { StringBuilder builder = new StringBuilder(); for (Integer keyCode : keyCodes) { if (!builder.toString().isEmpty()) { builder.append(" + "); } builder.append(keyCode); } return String.format("(%s)", builder); } }
C#
#if PLAY_GAMES_PC using System.Text; using Java.Lang; using Java.Util; using Google.Android.Libraries.Play.Games.Inputmapping; using Google.Android.Libraries.Play.Games.Inputmapping.Datamodel; using UnityEngine; public class InputSDKRemappingListener : InputRemappingListenerCallbackHelper { public override void OnInputMapChanged(InputMap inputMap) { Debug.Log("Received update on remapped controls."); if (inputMap.InputRemappingOption() == InputEnums.REMAP_OPTION_DISABLED) { return; } List<InputGroup> inputGroups = inputMap.InputGroups(); for (int i = 0; i < inputGroups.Size(); i ++) { InputGroup inputGroup = inputGroups.Get(i); if (inputGroup.InputRemappingOption() == InputEnums.REMAP_OPTION_DISABLED) { continue; } List<InputAction> inputActions = inputGroup.InputActions(); for (int j = 0; j < inputActions.Size(); j ++) { InputAction inputAction = inputActions.Get(j); if (inputAction.InputRemappingOption() != InputEnums.REMAP_OPTION_DISABLED) { // Found action remapped by user ProcessRemappedAction(inputAction); } } } } private void ProcessRemappedAction(InputAction remappedInputAction) { InputControls remappedInputControls = remappedInputAction.RemappedInputControls(); List<Integer> remappedKeycodes = remappedInputControls.Keycodes(); List<Integer> mouseActions = remappedInputControls.MouseActions(); string version = remappedInputAction.InputActionId().VersionString(); long remappedActionId = remappedInputAction.InputActionId().UniqueId(); InputAction currentInputAction; if (string.IsNullOrEmpty(version) || string.Equals( version, InputSDKMappingProvider.INPUT_MAP_VERSION)) { currentInputAction = GetCurrentVersionInputAction(remappedActionId); } else { Debug.Log("Detected version of used-saved input action defers" + " from current version"); currentInputAction = GetCurrentVersionInputActionFromPreviousVersion( remappedActionId, version); } if (currentInputAction == null) { Debug.LogError(string.Format( "Input Action with id {0} and version {1} not found", remappedActionId, string.IsNullOrEmpty(version) ? "UNKNOWN" : version)); return; } InputControls originalControls = currentInputAction.InputControls(); List<Integer> originalKeycodes = originalControls.Keycodes(); Debug.Log(string.Format( "Found Input Action with id {0} remapped from key {1} to key {2}", remappedActionId, KeyCodesToString(originalKeycodes), KeyCodesToString(remappedKeycodes))); // TODO: update HUD according to the controls of the user } private InputAction GetCurrentVersionInputAction( long inputActionId) { List<InputGroup> inputGroups = InputSDKMappingProvider.gameInputMap.InputGroups(); for (int i = 0; i < inputGroups.Size(); i++) { InputGroup inputGroup = inputGroups.Get(i); List<InputAction> inputActions = inputGroup.InputActions(); for (int j = 0; j < inputActions.Size(); j++) { InputAction inputAction = inputActions.Get(j); if (inputAction.InputActionId().UniqueId() == inputActionId) { return inputAction; } } } return null; } private InputAction GetCurrentVersionInputActionFromPreviousVersion( long inputActionId, string version) { // TODO: add logic to this method considering the diff between your // current and previous InputMap. return null; } private string KeyCodesToString(List<Integer> keycodes) { StringBuilder builder = new StringBuilder(); for (int i = 0; i < keycodes.Size(); i ++) { Integer keycode = keycodes.Get(i); if (builder.Length > 0) { builder.Append(" + "); } builder.Append(keycode.IntValue()); } return string.Format("({0})", builder.ToString()); } } #endif
InputRemappingListener
jest powiadamiany w momencie uruchomienia po załadowaniu zapisanych przez użytkownika mapowanych elementów sterujących oraz za każdym razem, gdy użytkownik zmapuje przyciski.
Inicjowanie
Jeśli używasz InputContexts
, ustaw kontekst dla każdej zmiany sceny, w tym pierwszy kontekst użyty w początkowej scenie. Ustawienie InputContext
musisz wykonać po zarejestrowaniu InputMap
.
Jeśli używasz usługi InputRemappingListeners
, aby otrzymywać powiadomienia o przemapowaniu zdarzeń, zarejestruj InputRemappingListener
przed zarejestrowaniem InputMappingProvider
. W przeciwnym razie gra może przeoczyć ważne zdarzenia w czasie uruchomienia.
Ten przykład pokazuje, jak zainicjować interfejs API:
Kotlin
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) if (isGooglePlayGamesOnPC()) { val inputMappingClient = Input.getInputMappingClient(this) // Register listener before registering the provider inputMappingClient.registerRemappingListener(InputSDKRemappingListener()) inputMappingClient.setInputMappingProvider( InputSDKProvider()) // Set the context after you have registered the provider. inputMappingClient.setInputContext(InputSDKProvider.menuSceneInputContext) } }
Java
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (isGooglePlayGamesOnPC()) { InputMappingClient inputMappingClient = Input.getInputMappingClient(this); // Register listener before registering the provider inputMappingClient.registerRemappingListener( new InputSDKRemappingListener()); inputMappingClient.setInputMappingProvider( new InputSDKProvider()); // Set the context after you have registered the provider inputMappingClient.setInputContext(InputSDKProvider.menuSceneInputContext); } }
C#
#if PLAY_GAMES_PC using Google.Android.Libraries.Play.Games.Inputmapping; using Google.Android.Libraries.Play.Games.InputMapping.ExternalType.Android.Content; using Google.LibraryWrapper.Java; #endif public class GameManager : MonoBehaviour { #if PLAY_GAMES_PC private InputSDKMappingProvider _inputMapProvider = new InputSDKMappingProvider(); private InputMappingClient _inputMappingClient; #endif public void Awake() { #if PLAY_GAMES_PC Context context = (Context)Utils.GetUnityActivity().GetRawObject(); _inputMappingClient = Google.Android.Libraries.Play.Games.Inputmapping .Input.GetInputMappingClient(context); // Register listener before registering the provider. _inputMappingClient.RegisterRemappingListener( new InputSDKRemappingListener()); _inputMappingClient.SetInputMappingProvider(_inputMapProvider); // Register context after you have registered the provider. _inputMappingClient.SetInputContext( InputSDKMappingProvider.menuSceneInputContext); #endif } }
Uporządkuj
zarejestruj instancję InputMappingProvider
i wszystkie instancje InputRemappingListener
, gdy gra jest zamknięta, chociaż pakiet SDK do wprowadzania danych jest na tyle inteligentny, że zapobiega wyciekom zasobów, jeśli tego nie zrobisz:
Kotlin
override fun onDestroy() { if (isGooglePlayGamesOnPC()) { val inputMappingClient = Input.getInputMappingClient(this) inputMappingClient.clearInputMappingProvider() inputMappingClient.clearRemappingListener() } super.onDestroy() }
Java
@Override protected void onDestroy() { if (isGooglePlayGamesOnPC()) { InputMappingClient inputMappingClient = Input.getInputMappingClient(this); inputMappingClient.clearInputMappingProvider(); inputMappingClient.clearRemappingListener(); } super.onDestroy(); }
C#
public class GameManager : MonoBehaviour { private void OnDestroy() { #if PLAY_GAMES_PC _inputMappingClient.ClearInputMappingProvider(); _inputMappingClient.ClearRemappingListener(); #endif } }
Test
Implementację pakietu Input SDK możesz przetestować, ręcznie otwierając nakładkę, aby wyświetlić interfejs odtwarzacza, lub za pomocą powłoki adb na potrzeby automatycznego testowania i weryfikacji.
Emulator Gier Google Play na PC sprawdza poprawność mapy danych pod kątem typowych błędów. W przypadku takich sytuacji jak zduplikowane unikalne identyfikatory, używanie różnych map danych wejściowych lub niespełnienie reguł przemapowania (jeśli przemapowanie jest włączone) nakładka wyświetla komunikat o błędzie:
Sprawdź implementację pakietu SDK do wprowadzania danych za pomocą polecenia adb
w wierszu poleceń.
Aby uzyskać bieżącą mapę wejściową, użyj polecenia adb shell
(zastąp MY.PACKAGE.NAME
nazwą gry):
adb shell dumpsys input_mapping_service --get MY.PACKAGE.NAME
Jeśli rejestracja InputMap
przebiegnie pomyślnie, zobaczysz dane wyjściowe podobne do tych:
Getting input map for com.example.inputsample...
Successfully received the following inputmap:
# com.google.android.libraries.play.games.InputMap@d73526e1
input_groups {
group_label: "Basic Movement"
input_actions {
action_label: "Jump"
input_controls {
keycodes: 51
keycodes: 19
}
unique_id: 0
}
input_actions {
action_label: "Left"
input_controls {
keycodes: 29
keycodes: 21
}
unique_id: 1
}
input_actions {
action_label: "Right"
input_controls {
keycodes: 32
keycodes: 22
}
unique_id: 2
}
input_actions {
action_label: "Use"
input_controls {
keycodes: 33
keycodes: 66
mouse_actions: MOUSE_LEFT_CLICK
mouse_actions_value: 0
}
unique_id: 3
}
}
input_groups {
group_label: "Special Input"
input_actions {
action_label: "Jump"
input_controls {
keycodes: 51
keycodes: 19
keycodes: 62
mouse_actions: MOUSE_LEFT_CLICK
mouse_actions_value: 0
}
unique_id: 4
}
input_actions {
action_label: "Duck"
input_controls {
keycodes: 47
keycodes: 20
keycodes: 113
mouse_actions: MOUSE_RIGHT_CLICK
mouse_actions_value: 1
}
unique_id: 5
}
}
mouse_settings {
allow_mouse_sensitivity_adjustment: true
invert_mouse_movement: true
}
Lokalizacja
Pakiet SDK do wprowadzania danych nie korzysta z systemu lokalizacji Androida. W rezultacie podczas przesyłania InputMap
musisz podać zlokalizowane ciągi znaków. Możesz też użyć systemu lokalizacji silnika gry.
Proguard
Jeśli używasz narzędzia Proguard do kompresji gry, dodaj do pliku konfiguracyjnego proguarda te reguły, aby mieć pewność, że pakiet SDK nie zostanie usunięty z ostatecznego pakietu:
-keep class com.google.android.libraries.play.hpe.** { *; }
-keep class com.google.android.libraries.play.games.inputmapping.** { *; }
Co dalej
Po zintegrowaniu pakietu SDK do obsługi danych wejściowych z grą możesz kontynuować spełnianie pozostałych wymagań Gier Google Play na PC. Więcej informacji znajdziesz w artykule Pierwsze kroki z Grami Google Play na PC.