Z tego dokumentu dowiesz się, jak skonfigurować i wyświetlać pakiet SDK do obsługi danych wejściowych w grach, które obsługują Gry Google Play na PC. Obejmują one dodanie pakietu SDK do gry i wygenerowanie mapy wejść, która zawiera przypisania działań w grze do danych wejściowych użytkownika.
Zanim rozpoczniesz
Zanim dodasz do gry pakiet SDK do obsługi danych wejściowych, musisz obsługiwać dane wejściowe z klawiatury i myszy za pomocą systemu wejściowego silnika gry.
Pakiet Input SDK przekazuje do Gier Google Play na PC informacje o tym, jakich elementów sterujących używa Twoja gra, aby można było wyświetlać je użytkownikowi. Może też opcjonalnie zezwalać użytkownikom na zmianę mapowania klawiatury.
Każdy element sterujący to InputAction (np. „J” w przypadku „Skoku”). InputActions są uporządkowane 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 momentach gry.
Możesz włączyć automatyczne mapowanie klawiatury, ale jeśli wolisz udostępnić własny interfejs mapowania sterowania, możesz wyłączyć mapowanie pakietu SDK do obsługi danych wejściowych.
Ten diagram sekwencji opisuje, jak działa interfejs API pakietu Input SDK:

Gdy gra zaimplementuje pakiet Input SDK, elementy sterujące będą wyświetlane w nakładce Gier Google Play na PC.
Nakładka Gier Google Play na PC
Nakładka Gier Google Play na PC („nakładka”) wyświetla elementy sterujące zdefiniowane przez Twoją grę. Użytkownicy mogą w dowolnym momencie otworzyć nakładkę, naciskając Shift + Tab.

Sprawdzone metody projektowania powiązań klawiszy
Podczas projektowania przypisań klawiszy pamiętaj o tych sprawdzonych metodach:
- Grupuj
InputActionsw logicznie powiązaneInputGroups, aby ułatwić poruszanie się po elementach sterujących i ich znajdowanie podczas rozgrywki. - Przypisz każdy element
InputGroupdo co najwyżej jednego elementuInputContext. Drobne ziarnoInputMapzapewnia lepsze wrażenia podczas poruszania się po elementach sterujących w nakładce. - Utwórz
InputContextdla każdego typu sceny w grze. Zwykle możesz używać jednego taguInputContextdo wszystkich scen przypominających menu. Używaj różnychInputContextsw przypadku minigier w swojej grze lub alternatywnych elementów sterujących w jednej scenie. - Jeśli 2 działania mają używać tego samego klawisza w tym samym
InputContext, użyj ciągu etykiety, np. „Interakcja / Strzelanie”. - Jeśli 2 klucze mają być powiązane z tym samym
InputAction, użyj 2 różnychInputActions, które wykonują to samo działanie w grze. Możesz użyć tego samego ciągu znaków etykiety w przypadku obu atrybutówInputActions, ale ich identyfikatory muszą być różne. - Jeśli klawisz modyfikujący jest stosowany do zestawu klawiszy, rozważ użycie pojedynczego klawisza
InputActionz klawiszem modyfikującym zamiast wielu klawiszyInputActions, które łączą klawisz modyfikujący (np. użyj Shift i W, A, S, D zamiast Shift + W, Shift + A, Shift + S, Shift + D). - Remapowanie danych wejściowych jest automatycznie wyłączane, gdy użytkownik wpisuje tekst w polach tekstowych. Postępuj zgodnie ze sprawdzonymi metodami wdrażania pól tekstowych na Androidzie, aby mieć pewność, że Android może wykrywać pola tekstowe w Twojej grze i zapobiegać zakłócaniu ich działania przez ponownie zmapowane klawisze. Jeśli w grze musisz używać nietypowych pól tekstowych, możesz użyć
setInputContext()zInputContextzawierającym pustą listęInputGroups, aby ręcznie wyłączyć ponowne mapowanie. - Jeśli Twoja gra obsługuje zmianę przypisań klawiszy, rozważ zaktualizowanie przypisań klawiszy. Jest to operacja wrażliwa, która może powodować konflikty z wersjami zapisanymi przez użytkownika. W miarę możliwości unikaj zmiany identyfikatorów istniejących elementów sterujących.
Funkcja ponownego mapowania
Gry Google Play na PC obsługują zmianę przypisań klawiszy na podstawie powiązań klawiszy, które Twoja gra udostępnia za pomocą pakietu Input SDK. Jest to opcjonalne i można to całkowicie wyłączyć. Możesz na przykład udostępnić własny interfejs do zmiany przypisań klawiszy. Aby wyłączyć ponowne mapowanie w grze, wystarczy określić, że opcja ponownego mapowania jest wyłączona dla InputMap (więcej informacji znajdziesz w artykule Tworzenie InputMap).
Aby uzyskać dostęp do tej funkcji, użytkownicy muszą otworzyć nakładkę, a następnie kliknąć działanie, które chcą zmienić. Po każdym zdarzeniu ponownego mapowania Gry Google Play na PC mapują każdy ponownie zmapowany przez użytkownika element sterujący na domyślne elementy sterujące, których oczekuje Twoja gra, więc nie musi ona wiedzieć o ponownym mapowaniu przez gracza. Opcjonalnie możesz zaktualizować komponenty używane do wyświetlania elementów sterujących klawiatury w grze, dodając wywołanie zwrotne do ponownego mapowania zdarzeń.

Gry Google Play na PC przechowują lokalnie zmienione mapowania elementów sterujących dla każdego użytkownika, dzięki czemu są one zachowywane podczas kolejnych sesji gry. Te informacje są przechowywane na dysku tylko na platformie PC i nie mają wpływu na korzystanie z urządzeń mobilnych. Dane sterujące są usuwane, gdy użytkownik odinstaluje lub ponownie zainstaluje Gry Google Play na PC. Te dane nie są trwałe na wielu komputerach.
Aby obsługiwać funkcję ponownego mapowania w swojej grze, unikaj tych ograniczeń:
Ograniczenia ponownego mapowania
Funkcje zmiany przypisania klawiszy można wyłączyć w grze, jeśli przypisania klawiszy obejmują którykolwiek z tych przypadków:
- Skróty składające się z wielu klawiszy
InputActions, które nie są kombinacją klawisza modyfikującego i klawisza niemodyfikującego. Na przykład Shift + A jest prawidłowe, ale A + B, Ctrl + Alt lub Shift + A + Tab nie. InputMapzawieraInputActions,InputGroupslubInputContextsz powtórzonymi unikalnymi identyfikatorami.
Ograniczenia ponownego mapowania
Podczas projektowania przypisań klawiszy do ponownego mapowania weź pod uwagę te ograniczenia:
- Zmiana mapowania na kombinacje klawiszy nie jest obsługiwana. Na przykład użytkownicy nie mogą zmienić przypisania Shift + A na Ctrl + B ani A na Shift + A.
- Zmiana mapowania nie jest obsługiwana w przypadku
InputActionsz przyciskami myszy. Na przykład Shift + prawy przycisk myszy nie można ponownie przypisać.
Testowanie ponownego mapowania klawiszy w emulatorze Gier Google Play na PC
Funkcję ponownego mapowania możesz włączyć w dowolnym momencie w emulatorze Gier Google Play na PC, wydając to polecenie adb:
adb shell dumpsys input_mapping_service --set RemappingFlagValue true
Nakładka zmieni się tak jak na tym obrazie:

Dodawanie pakietu SDK
Zainstaluj Input SDK zgodnie z platformą programowania.
Java i Kotlin
Pobierz Input SDK na Javę 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 Input SDK to standardowy pakiet Unity z kilkoma zależnościami.
Wymagana jest instalacja pakietu ze wszystkimi zależnościami. Pakiety można zainstalować na kilka sposobów.
Zainstaluj .unitypackage
Pobierz plik unitypackage pakietu Input SDK wraz ze wszystkimi zależnościami. .unitypackage możesz zainstalować, wybierając Assets > Import package > Custom Package i znajdując pobrany plik.
Instalowanie za pomocą UPM
Możesz też zainstalować pakiet za pomocą Menedżera pakietów Unity, pobierając .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 wybierając plik 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 Input SDK znajdziesz w AGDK Tunnel w przypadku gier w Kotlinie lub Javie oraz w Trivial Kart w przypadku gier w Unity.
Generowanie powiązań klawiszy
Zarejestruj powiązania klawiszy, tworząc InputMap i zwracając go za pomocą InputMappingProvider. Poniższy 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
Określ działania wejściowe
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 ponowne mapowanie, możesz określić, co można ponownie mapować.InputActions Jeśli gra nie obsługuje mapowania, wyłącz opcję mapowania dla wszystkich InputActions. Pakiet Input SDK jest jednak wystarczająco inteligentny, aby wyłączyć mapowanie, jeśli nie jest ono obsługiwane w 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ż reprezentować dane wejściowe z myszy. W tym przykładzie kliknięcie lewym przyciskiem jest ustawione na działanie przenoszenia:
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 elementu 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 Input SDK umożliwia łączenie przycisków myszy i klawiatury w jedno działanie. Ten przykład pokazuje, że naciśnięcie jednocześnie klawiszy
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 );

Obiekt InputAction ma te pola:
ActionLabel: ciąg znaków wyświetlany w interfejsie, który reprezentuje to działanie. Lokalizacja nie jest wykonywana automatycznie, więc zrób to z wyprzedzeniem.InputControls: określa elementy sterujące, których używa to działanie. Elementy sterujące są mapowane na spójne symbole w nakładce.InputActionId: obiektInputIdentifier, który przechowuje identyfikator numeru i wersjęInputAction(więcej informacji znajdziesz w artykule Identyfikatory kluczy śledzenia).InputRemappingOption: jedna z wartościInputEnums.REMAP_OPTION_ENABLEDlubInputEnums.REMAP_OPTION_DISABLED. Określa, czy działanie można ponownie przypisać. Jeśli gra nie obsługuje ponownego mapowania, możesz pominąć to pole lub po prostu ustawić je jako wyłączone.RemappedInputControls: obiektInputControlstylko do odczytu, który służy do odczytywania zestawu kluczy zmapowanego przez użytkownika podczas zdarzeń ponownego mapowania (używany do otrzymywania powiadomień o zdarzeniach ponownego mapowania).
InputControls reprezentuje dane wejściowe powiązane z działaniem i zawiera te pola:
AndroidKeycodes: to lista liczb całkowitych reprezentujących dane wejściowe z klawiatury powiązane z działaniem. Są one zdefiniowane w klasie KeyEvent lub w klasie AndroidKeycode w przypadku Unity.MouseActions: to lista wartościMouseActionreprezentujących dane wejściowe myszy powiązane z tym działaniem.
Określ grupy wejściowe
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ć unikalny w ramach wszystkich InputGroups w Twojej grze.
Grupowanie działań wejściowych ułatwia graczowi znalezienie odpowiedniego powiązania klawiszy w bieżącym kontekście.
Jeśli obsługujesz ponowne mapowanie, możesz określić, co można ponownie mapować.InputGroups Jeśli gra nie obsługuje mapowania, wyłącz opcję mapowania dla wszystkich InputGroups. Pakiet Input SDK jest jednak wystarczająco inteligentny, aby wyłączyć mapowanie, jeśli nie jest ono obsługiwane w 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 );
Poniższy przykład przedstawia grupy wejściowe Elementy sterujące drogą i Elementy sterujące menu w nakładce:

InputGroup zawiera te pola:
GroupLabel: ciąg znaków, który ma być wyświetlany w nakładce i może służyć do logicznego grupowania zestawu działań. Ten ciąg nie jest automatycznie lokalizowany.InputActions: lista obiektówInputActionzdefiniowanych w poprzednim kroku. Wszystkie te działania są wyświetlane wizualnie pod nagłówkiem grupy.InputGroupId: obiektInputIdentifier, który przechowuje identyfikator liczbowy i wersjęInputGroup. Więcej informacji znajdziesz w artykule Identyfikatory kluczy śledzenia.InputRemappingOption: jedna z wartościInputEnums.REMAP_OPTION_ENABLEDlubInputEnums.REMAP_OPTION_DISABLED. Jeśli ta opcja jest wyłączona, wszystkie obiekty należące do tej grupy będą miały wyłączone ponowne mapowanie, nawet jeśli określono, że opcja ponownego mapowania jest włączona.InputActionJeśli ta opcja jest włączona, wszystkie działania należące do tej grupy można ponownie przypisać, chyba że poszczególne działania mają wyłączoną tę możliwość.
Określanie kontekstów wejściowych
InputContexts umożliwia grze używanie różnych zestawów elementów sterujących klawiatury w różnych scenach. Na przykład:
- Możesz określić różne zestawy 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 sposobu poruszania się w grze, np. jazdy samochodem lub chodzenia.
- Możesz określić różne zestawy danych wejściowych w zależności od bieżącego stanu gry, np. podczas poruszania się po mapie świata lub grania na poszczególnych poziomach.
Gdy używasz InputContexts, nakładka wyświetla najpierw grupy kontekstu w użyciu. Aby włączyć to działanie, wywołaj funkcję setInputContext(), aby ustawić kontekst za każdym razem, gdy gra przechodzi do innej sceny. Ilustruje to poniższy obraz: w scenie „prowadzenie pojazdu” u góry nakładki wyświetlają się elementy sterujące drogą. Po otwarciu menu „Sklep” u góry nakładki wyświetlają się działania „Elementy sterujące menu”.

Aktualizacje nakładki są realizowane przez ustawienie innego parametru InputContext w różnych momentach gry. Aby to zrobić:
- Grupuj
InputActionsz powiązanymi logicznie działaniami za pomocąInputGroups - Przypisz te
InputGroupsdoInputContextw różnych częściach gry.
InputGroups należące do tego samegoInputContextnie mogą mieć sprzecznychInputActions, w których używany jest ten sam klucz. Dobrze jest przypisać każdy InputGroup do jednego InputContext.
Poniższy przykładowy kod pokazuje 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 identyfikator numeru i wersjęInputContext(więcej informacji znajdziesz w artykule 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 wejścia
InputMap to zbiór wszystkich obiektów InputGroup dostępnych w grze, a tym samym wszystkich obiektów InputAction, z którymi gracz może wejść w interakcję.
Podczas raportowania przypisań klawiszy tworzysz InputMap ze wszystkimi InputGroups używanymi w grze.
Jeśli gra nie obsługuje ponownego mapowania, wyłącz tę opcję i usuń zarezerwowane klawisze.
W tym przykładzie tworzymy InputMap, który służy do raportowania kolekcji 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 wejściowe zgłoszone przez grę. Grupy są wyświetlane w kolejności w nakładce, chyba że określono bieżące grupy w użyciu, wywołującsetInputContext().MouseSettings: obiektMouseSettingswskazuje, że czułość myszy można dostosować i że mysz jest odwrócona na osi Y.InputMapId:InputIdentifierobiekt, który przechowuje identyfikator liczbowy i wersjęInputMap(więcej informacji znajdziesz w sekcji Identyfikatory kluczy śledzenia).InputRemappingOption: jedna z wartościInputEnums.REMAP_OPTION_ENABLEDlubInputEnums.REMAP_OPTION_DISABLED. Określa, czy funkcja ponownego mapowania jest włączona.ReservedControls: listaInputControls, których użytkownicy nie będą mogli ponownie przypisać.
Śledzenie identyfikatorów kluczy
Obiekty InputAction, InputGroup, InputContext i InputMap zawierają obiekt InputIdentifier, który przechowuje unikalny identyfikator liczbowy i identyfikator wersji w formie ciągu znaków.
Śledzenie wersji tekstowej obiektów jest opcjonalne, ale zalecane, aby śledzić wersje InputMap. Jeśli wersja ciągu znaków nie zostanie podana, ciąg znaków będzie pusty. W przypadku obiektów InputMap wymagana jest wersja tekstowa.
W przykładzie poniżej przypisujemy wersję ciągu znaków 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
Identyfikatory obiektów InputAction muszą być unikalne we wszystkich InputActions w InputMap. Podobnie identyfikatory obiektów InputGroup muszą być unikalne we wszystkich InputGroups w InputMap. Poniższy przykład pokazuje, jak używać elementu enum do śledzenia unikalnych identyfikatorów obiektu:
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 ustawiony w celu jednoznacznego zidentyfikowania danego zbioru danych wejściowych.VersionString: ciąg znaków czytelny dla człowieka, który identyfikuje wersję danych wejściowych między 2 wersjami zmian danych wejściowych.
Otrzymywanie powiadomień o zdarzeniach ponownego mapowania (opcjonalnie)
Otrzymuj powiadomienia o zdarzeniach ponownego mapowania, aby być na bieżąco z klawiszami używanymi w Twojej 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.
Ilustracja poniżej pokazuje przykład takiego działania. Po ponownym przypisaniu klawiszy

Można to osiągnąć, rejestrując InputRemappingListenerwywołanie zwrotne. Aby zaimplementować 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 otrzymuje powiadomienie w momencie uruchomienia po wczytaniu zapisanych przez użytkownika zmienionych ustawień sterowania oraz za każdym razem, gdy użytkownik zmieni przypisanie klawiszy.
Inicjowanie
Jeśli używasz InputContexts, ustawiaj kontekst przy każdym przejściu do nowej sceny, w tym pierwszy kontekst używany w początkowej scenie. Musisz ustawić InputContext po zarejestrowaniu InputMap.
Jeśli używasz InputRemappingListeners, aby otrzymywać powiadomienia o zdarzeniach ponownego mapowania, zarejestruj InputRemappingListener przed zarejestrowaniem InputMappingProvider. W przeciwnym razie Twoja gra może przegapić ważne zdarzenia podczas uruchamiania.
Poniższy 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
Po zamknięciu gry wyrejestruj instancję InputMappingProvider i wszystkie instancje InputRemappingListener. Pakiet Input SDK jest jednak wystarczająco inteligentny, aby uniknąć wycieku zasobów, nawet 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
Możesz przetestować implementację pakietu Input SDK, ręcznie otwierając nakładkę, aby zobaczyć, jak wygląda odtwarzacz, lub za pomocą powłoki adb w celu automatycznego testowania i weryfikacji.
Emulator Gier Google Play na PC sprawdza poprawność mapy wejść pod kątem typowych błędów. W przypadku scenariuszy takich jak zduplikowane unikalne identyfikatory, używanie różnych map wejściowych lub niepowodzenie reguł ponownego mapowania (jeśli ponowne mapowanie jest włączone) nakładka wyświetla komunikat o błędzie, jak poniżej:

Sprawdź wdrożenie pakietu Input SDK za pomocą polecenia adb w wierszu poleceń.
Aby uzyskać bieżącą mapę wejść, użyj tego polecenia adb shell (zastąp MY.PACKAGE.NAME nazwą gry):
adb shell dumpsys input_mapping_service --get MY.PACKAGE.NAME
Jeśli rejestracja InputMap zakończy się 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 nie korzysta z systemu lokalizacji Androida. W związku z tym podczas przesyłania InputMap musisz podać zlokalizowane ciągi znaków. Możesz też użyć systemu lokalizacji silnika gry.
Proguard
Jeśli do minifikacji gry używasz Proguarda, dodaj do pliku konfiguracji Proguarda te reguły, aby pakiet SDK nie został usunięty z pakietu końcowego:
-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 przejść do pozostałych wymagań dotyczących Gier Google Play na PC. Więcej informacji znajdziesz w artykule Pierwsze kroki z Grami Google Play na PC.