In diesem Dokument wird beschrieben, wie Sie das Input SDK in Spielen einrichten und anzeigen lassen, die Google Play Games auf dem PC unterstützen. Zu den Aufgaben gehören das Hinzufügen des SDK zu Ihrem Spiel und das Generieren einer Eingabezuordnung, die die Zuweisungen von Spielaktionen zu Nutzereingaben enthält.
Vorbereitung
Bevor Sie das Input SDK in Ihr Spiel einbinden, müssen Sie die Eingabe über Tastatur und Maus mit dem Eingabesystem Ihrer Spiele-Engine unterstützen.
Das Input SDK liefert Informationen an Google Play Games auf dem PC darüber, welche Steuerelemente in Ihrem Spiel verwendet werden, damit sie dem Nutzer angezeigt werden können. Optional kann auch die Tastenzuordnung für Nutzer erlaubt werden.
Jede Steuerung ist ein InputAction (z. B. „J“ für „Jump“). Sie organisieren Ihre InputActions in InputGroups. Ein InputGroup kann einen anderen Modus in Ihrem Spiel darstellen, z. B. „Fahren“, „Gehen“ oder „Hauptmenü“. Sie können auch InputContexts verwenden, um anzugeben, welche Gruppen zu verschiedenen Zeitpunkten des Spiels aktiv sind.
Sie können die Tastenzuordnung automatisch vornehmen lassen. Wenn Sie jedoch lieber eine eigene Benutzeroberfläche für die Neuzuordnung von Steuerelementen bereitstellen möchten, können Sie die Neuzuordnung des Input SDK deaktivieren.
Das folgende Sequenzdiagramm beschreibt die Funktionsweise der API des Input SDK:

Wenn in Ihrem Spiel das Input SDK implementiert ist, werden die Steuerelemente im Overlay von Google Play Games auf dem PC angezeigt.
Das Google Play Games auf dem PC-Overlay
Im Google Play Games auf dem PC-Overlay („das Overlay“) werden die von Ihrem Spiel definierten Steuerelemente angezeigt. Nutzer können das Overlay jederzeit durch Drücken von Umschalttaste + Tabulatortaste aufrufen.

Best Practices für das Design von Tastenzuweisungen
Beachten Sie beim Entwerfen Ihrer Tastenzuweisungen die folgenden Best Practices:
- Gruppieren Sie Ihre
InputActionsin logisch zusammenhängendeInputGroups, um die Navigation und Auffindbarkeit der Steuerelemente während des Spiels zu verbessern. - Weisen Sie jedes
InputGrouphöchstens einemInputContextzu. Eine feine GranularitätInputMapführt zu einer besseren Navigation in den Steuerelementen im Overlay. - Erstellen Sie für jeden unterschiedlichen Szenentyp Ihres Spiels ein
InputContext. Normalerweise können Sie ein einzelnesInputContextfür alle Szenen verwenden, die wie ein Menü aufgebaut sind. Verwenden Sie verschiedeneInputContextsfür Minispiele in Ihrem Spiel oder für alternative Steuerelemente für eine einzelne Szene. - Wenn für zwei Aktionen derselbe Schlüssel unter demselben
InputContextverwendet werden soll, verwenden Sie den Labelstring „Interact / Fire“ (Interagieren / Auslösen). - Wenn zwei Tasten an dieselbe
InputActiongebunden werden sollen, verwenden Sie zwei verschiedeneInputActions, die dieselbe Aktion in Ihrem Spiel ausführen. Sie können denselben Label-String für beideInputActionsverwenden, aber die ID muss unterschiedlich sein. - Wenn eine Modifikatortaste auf eine Reihe von Tasten angewendet wird, sollten Sie eine einzelne
InputActionmit der Modifikatortaste anstelle mehrererInputActionsverwenden, die die Modifikatortaste kombinieren (z. B. Umschalttaste und W, A, S, D anstelle von Umschalttaste + W, Umschalttaste + A, Umschalttaste + S, Umschalttaste + D). - Die Eingabezuordnung wird automatisch deaktiviert, wenn der Nutzer Text in Textfelder eingibt. Befolgen Sie die Best Practices für die Implementierung von Android-Textfeldern, damit Android Textfelder in Ihrem Spiel erkennen und verhindern kann, dass neu zugewiesene Tasten sie beeinträchtigen. Wenn in Ihrem Spiel unkonventionelle Textfelder verwendet werden müssen, können Sie
setInputContext()mit einemInputContextverwenden, das eine leere Liste vonInputGroupsenthält, um die Neuzuordnung manuell zu deaktivieren. - Wenn dein Spiel das Neubelegen von Tasten unterstützt, solltest du die Tastenbelegung als sensiblen Vorgang betrachten, der mit den vom Nutzer gespeicherten Versionen in Konflikt geraten kann. Vermeiden Sie es nach Möglichkeit, die IDs vorhandener Steuerelemente zu ändern.
Funktion zum Neuzuordnen von Tasten
Google Play Games auf dem PC unterstützt die Neubelegung von Tastatursteuerungen basierend auf den Tastenbelegungen, die Ihr Spiel über das Input SDK bereitstellt. Dies ist optional und kann vollständig deaktiviert werden. Möglicherweise möchten Sie beispielsweise eine eigene Tastaturbelegungsschnittstelle bereitstellen. Wenn Sie die Neubelegung für Ihr Spiel deaktivieren möchten, müssen Sie nur die Option für die Neubelegung für Ihr InputMap deaktivieren (weitere Informationen finden Sie unter InputMap erstellen).
Um auf diese Funktion zuzugreifen, müssen Nutzer das Overlay öffnen und dann auf die Aktion klicken, die sie neu zuordnen möchten. Nach jedem Ereignis zum Neubelegen von Tasten ordnet Google Play Games auf dem PC jede vom Nutzer neu belegte Steuerung den Standardsteuerungen zu, die dein Spiel erwartet. Dein Spiel muss also nicht wissen, dass der Spieler Tasten neu belegt hat. Optional können Sie die Assets, die zum Anzeigen der Tastatursteuerung in Ihrem Spiel verwendet werden, aktualisieren, indem Sie einen Callback für das Neuzuordnen von Ereignissen hinzufügen.

In Google Play Games auf dem PC werden neu zugewiesene Steuerelemente lokal für jeden Nutzer gespeichert, sodass die Steuerung über Gaming-Sitzungen hinweg beibehalten wird. Diese Informationen werden nur für die PC-Plattform auf der Festplatte gespeichert und haben keine Auswirkungen auf die mobile Nutzung. Kontrolldaten werden gelöscht, wenn der Nutzer Google Play Games auf dem PC deinstalliert oder neu installiert. Diese Daten werden nicht auf mehreren PCs gespeichert.
Damit die Funktion zum Neubelegen von Tasten in Ihrem Spiel unterstützt wird, sollten Sie die folgenden Einschränkungen vermeiden:
Einschränkungen bei der Neuzuordnung
Die Funktion zum Neubelegen von Tasten kann in Ihrem Spiel deaktiviert werden, wenn die Tastenbelegungen einen der folgenden Fälle enthalten:
- Tastenkombinationen aus mehreren Tasten
InputActions, die nicht aus einer Modifikatortaste und einer Nicht-Modifikatortaste bestehen. Beispiel: Umschalttaste + A ist gültig, A + B, Strg + Alt oder Umschalttaste + A + Tab hingegen nicht. - Das Feld
InputMapenthältInputActions,InputGroupsoderInputContextsmit wiederholten eindeutigen IDs.
Einschränkungen bei der Neuzuordnung
Beachten Sie beim Entwerfen Ihrer Tastenzuweisungen für die Neubelegung die folgenden Einschränkungen:
- Das Neubelegen von Tastenkombinationen wird nicht unterstützt. Nutzer können beispielsweise Umschalttaste + A nicht Strg + B oder A nicht Umschalttaste + A zuordnen.
- Die Neuzuordnung wird für
InputActionsmit Maustasten nicht unterstützt. Umschalt + Rechtsklick kann beispielsweise nicht neu zugewiesen werden.
Tastenbelegung im Emulator für Google Play Games auf dem PC testen
Sie können die Funktion zum Neubelegen von Tasten jederzeit im Google Play Games auf dem PC-Emulator aktivieren, indem Sie den folgenden ADB-Befehl ausführen:
adb shell dumpsys input_mapping_service --set RemappingFlagValue true
Die Änderung des Overlays ist im folgenden Bild zu sehen:

SDK hinzufügen
Installieren Sie das Input SDK entsprechend Ihrer Entwicklungsplattform.
Java und Kotlin
Sie erhalten das Input SDK für Java oder Kotlin, indem Sie Ihrer build.gradle-Datei auf Modulebene eine Abhängigkeit hinzufügen:
dependencies {
implementation 'com.google.android.libraries.play.games:inputmapping:1.1.1-beta'
...
}
Unity
Das Input SDK ist ein Standard-Unity-Paket mit mehreren Abhängigkeiten.
Das Paket muss mit allen Abhängigkeiten installiert werden. Es gibt mehrere Möglichkeiten, die Pakete zu installieren.
.unitypackage installieren
Laden Sie die unitypackage-Datei des Input SDK mit allen zugehörigen Abhängigkeiten herunter. Sie können das .unitypackage installieren, indem Sie Assets > Import package > Custom Package auswählen und die heruntergeladene Datei suchen.
Mit UPM installieren
Alternativ können Sie das Paket mit dem Unity Package Manager installieren, indem Sie .tgz herunterladen und die zugehörigen Abhängigkeiten installieren:
- 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 (oder die tgz-Datei aus diesem Archiv)
Mit OpenUPM installieren
Sie können das Paket mit OpenUPM installieren.
$ openupm add com.google.android.libraries.play.games.inputmapping
Beispielspiele
Beispiele für die Integration des Input SDK finden Sie im AGDK Tunnel für Kotlin- oder Java-Spiele und in Trivial Kart für Unity-Spiele.
Tastenzuweisungen generieren
Registrieren Sie Ihre Tastenzuweisungen, indem Sie ein InputMap erstellen und es mit einem InputMappingProvider zurückgeben. Das folgende Beispiel zeigt ein InputMappingProvider-Objekt:
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
Eingabeaktionen definieren
Mit der Klasse InputAction wird ein Schlüssel oder eine Tastenkombination einer Spielaktion zugeordnet. InputActions müssen für alle InputActions eindeutige IDs haben.
Wenn Sie die Neuzuordnung unterstützen, können Sie definieren, was neu zugeordnet werden kann.InputActions Wenn Ihr Spiel keine Neubelegung unterstützt, sollten Sie die Option für die Neubelegung für alle Ihre InputActions deaktivieren. Das Input SDK ist jedoch intelligent genug, um die Neubelegung zu deaktivieren, wenn sie in Ihrem InputMap nicht unterstützt wird.
In diesem Beispiel wird der
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 );

Aktionen können auch Mauseingaben darstellen. In diesem Beispiel wird Linksklick auf die Aktion Verschieben festgelegt:
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 );

Tastenkombinationen werden angegeben, indem Sie mehrere Tastencodes an Ihr InputAction übergeben. In diesem Beispiel wird
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 );

Mit dem Input SDK können Sie Maus- und Tastentasten für eine einzelne Aktion kombinieren. In diesem Beispiel wird gezeigt, dass durch gleichzeitiges Drücken von
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 );

„InputAction“ hat die folgenden Felder:
ActionLabel: Der String, der in der Benutzeroberfläche angezeigt wird, um diese Aktion darzustellen. Die Lokalisierung erfolgt nicht automatisch. Sie müssen sie also im Voraus durchführen.InputControls: Definiert die Eingabesteuerelemente, die von dieser Aktion verwendet werden. Die Steuerelemente sind konsistenten Glyphen im Overlay zugeordnet.InputActionId:InputIdentifier-Objekt, in dem die Nummer-ID und die Version desInputActiongespeichert sind (weitere Informationen finden Sie unter Tracking Key IDs).InputRemappingOption: entwederInputEnums.REMAP_OPTION_ENABLEDoderInputEnums.REMAP_OPTION_DISABLED. Definiert, ob die Aktion neu zugeordnet werden kann. Wenn Ihr Spiel keine Neubelegung unterstützt, können Sie dieses Feld überspringen oder einfach deaktivieren.RemappedInputControls: schreibgeschütztesInputControls-Objekt zum Lesen des vom Nutzer bei Neuzuordnungsvorgängen festgelegten neu zugeordneten Schlüsselsatzes (wird verwendet, um über Neuzuordnungsvorgänge benachrichtigt zu werden).
InputControls steht für die mit einer Aktion verknüpften Eingaben und enthält die folgenden Felder::
AndroidKeycodes: Eine Liste von Ganzzahlen, die Tastatureingaben für eine Aktion darstellen. Sie werden in der Klasse KeyEvent oder der AndroidKeycode-Klasse für Unity definiert.MouseActions: Eine Liste vonMouseAction-Werten, die Mauseingaben für diese Aktion darstellen.
Eingabegruppen definieren
InputActions werden mit logisch zusammenhängenden Aktionen gruppiert, indem InputGroups verwendet wird, um die Navigation und die Auffindbarkeit von Steuerelementen im Overlay zu verbessern. Jede InputGroup-ID muss für alle InputGroups in Ihrem Spiel eindeutig sein.
Wenn Sie Ihre Eingabeaktionen in Gruppen organisieren, können Spieler die richtige Tastenbelegung für ihren aktuellen Kontext leichter finden.
Wenn Sie die Neuzuordnung unterstützen, können Sie definieren, was neu zugeordnet werden kann.InputGroups Wenn Ihr Spiel keine Neubelegung unterstützt, sollten Sie die Option für die Neubelegung für alle Ihre InputGroups deaktivieren. Das Input SDK ist jedoch intelligent genug, um die Neubelegung zu deaktivieren, wenn sie in Ihrem InputMap nicht unterstützt wird.
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 );
Im folgenden Beispiel werden die Eingabegruppen Straßensteuerung und Menüsteuerung im Overlay angezeigt:

InputGroup hat die folgenden Felder:
GroupLabel: Ein String, der im Overlay angezeigt wird und mit dem eine Reihe von Aktionen logisch gruppiert werden kann. Dieser String wird nicht automatisch lokalisiert.InputActions: Eine Liste vonInputAction-Objekten, die Sie im vorherigen Schritt definieren. Alle diese Aktionen werden unter der Gruppenüberschrift angezeigt.InputGroupId:InputIdentifier-Objekt, in dem die Nummer-ID und die Version desInputGroupgespeichert sind. Weitere Informationen finden Sie unter Tracking-Schlüssel-IDs.InputRemappingOption: entwederInputEnums.REMAP_OPTION_ENABLEDoderInputEnums.REMAP_OPTION_DISABLED. Wenn diese Option deaktiviert ist, wird die Neuzuordnung für alleInputAction-Objekte dieser Gruppe deaktiviert, auch wenn die Neuzuordnungsoption aktiviert ist. Wenn diese Option aktiviert ist, können alle Aktionen in dieser Gruppe neu zugeordnet werden, sofern sie nicht durch die einzelnen Aktionen deaktiviert wurden.
Eingabekontexte definieren
Mit InputContexts kann Ihr Spiel für verschiedene Szenen unterschiedliche Tastatursteuerungen verwenden. Beispiel:
- Sie können verschiedene Eingabesätze für die Menünavigation und die Bewegung im Spiel festlegen.
- Je nach Fortbewegungsart im Spiel, z. B. Fahren oder Gehen, können Sie verschiedene Eingabesätze angeben.
- Sie können je nach aktuellem Status Ihres Spiels unterschiedliche Eingabesätze angeben, z. B. für die Navigation in einer Oberwelt im Vergleich zum Spielen eines einzelnen Levels.
Bei Verwendung von InputContexts werden im Overlay zuerst die Gruppen des verwendeten Kontexts angezeigt. Rufen Sie setInputContext() auf, um den Kontext festzulegen, wenn Ihr Spiel in eine andere Szene wechselt. Das folgende Bild veranschaulicht dieses Verhalten: In der Szene „Fahren“ werden die Aktionen der Straßensteuerung oben im Overlay angezeigt. Wenn Sie das Menü „Store“ öffnen, werden die Aktionen für die Menüsteuerung oben im Overlay angezeigt.

Diese Overlay-Aktualisierungen werden durch Festlegen eines anderen InputContext an verschiedenen Stellen im Spiel erreicht. Gehen Sie dazu so vor:
InputActionsmit logisch zusammenhängenden Aktionen mithilfe vonInputGroupsgruppieren- Weisen Sie diese
InputGroupseinemInputContextfür die verschiedenen Teile Ihres Spiels zu.
InputGroups, die zur selbenInputContextgehören, dürfen keine widersprüchlichenInputActionsmit demselben Schlüssel haben. Es empfiehlt sich, jedem InputGroup eine einzelne InputContext zuzuweisen.
Der folgende Beispielcode veranschaulicht die InputContext-Logik:
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 hat die folgenden Felder:
LocalizedContextLabel: Ein String, der die Gruppen beschreibt, die zum Kontext gehören.InputContextId:InputIdentifier-Objekt, in dem die Nummer-ID und die Version desInputContextgespeichert sind (weitere Informationen finden Sie unter Tracking Key IDs).ActiveGroups: Eine Liste derInputGroups, die verwendet und oben im Overlay angezeigt werden sollen, wenn dieser Kontext aktiv ist.
Eingabeübersicht erstellen
Ein InputMap ist eine Sammlung aller InputGroup-Objekte, die in einem Spiel verfügbar sind, und daher aller InputAction-Objekte, die ein Spieler ausführen kann.
Wenn Sie Ihre Tastenzuweisungen melden, erstellen Sie ein InputMap mit allen InputGroups, die in Ihrem Spiel verwendet werden.
Wenn Ihr Spiel keine Neubelegung unterstützt, deaktivieren Sie die Option für die Neubelegung und lassen Sie die reservierten Tasten leer.
Im folgenden Beispiel wird ein InputMap erstellt, mit dem eine Sammlung von InputGroups gemeldet wird.
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 hat die folgenden Felder:
InputGroups: Die von Ihrem Spiel gemeldeten InputGroups. Die Gruppen werden im Overlay in der Reihenfolge angezeigt, in der sie definiert sind, sofern nicht die aktuellen Gruppen mitsetInputContext()aufgerufen werden.MouseSettings: DasMouseSettings-Objekt gibt an, dass die Mausempfindlichkeit angepasst werden kann und die Maus auf der Y-Achse invertiert ist.InputMapId:InputIdentifier-Objekt, in dem die Nummer-ID und die Version desInputMapgespeichert sind (weitere Informationen finden Sie unter Tracking Key IDs).InputRemappingOption: entwederInputEnums.REMAP_OPTION_ENABLEDoderInputEnums.REMAP_OPTION_DISABLED. Gibt an, ob das Remapping-Feature aktiviert ist.ReservedControls: Eine Liste vonInputControls, denen Nutzer keine neuen Tastenbelegungen zuweisen dürfen.
Schlüssel-IDs erfassen
Die Objekte InputAction, InputGroup, InputContext und InputMap enthalten ein InputIdentifier-Objekt, in dem eine eindeutige numerische ID und eine String-Versions-ID gespeichert sind.
Die String-Version Ihrer Objekte zu erfassen, ist optional, wird aber empfohlen, um die Versionen Ihrer InputMap zu erfassen. Wenn keine String-Version angegeben ist, ist der String leer. Für InputMap-Objekte ist eine String-Version erforderlich.
Im folgenden Beispiel wird InputActions oder InputGroups eine Stringversion zugewiesen:
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
Die Nummern-IDs von InputAction-Objekten müssen für alle InputActions in Ihrem InputMap eindeutig sein. Ebenso müssen InputGroup-Objekt-IDs für alle InputGroups in einem InputMap eindeutig sein. Im folgenden Beispiel wird gezeigt, wie Sie ein enum verwenden, um die eindeutigen IDs Ihres Objekts zu erfassen:
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 hat die folgenden Felder:
UniqueId: Eine eindeutige numerische ID, die einen bestimmten Satz von Eingabedaten eindeutig identifiziert.VersionString: Ein für Menschen lesbarer Versionsstring, der festgelegt ist, um eine Version von Eingabedaten zwischen zwei Versionen von Änderungen an Eingabedaten zu identifizieren.
Benachrichtigungen zu Neuzuordnungsereignissen erhalten (optional)
Sie erhalten Benachrichtigungen zu Neubelegungsereignissen, damit Sie über die in Ihrem Spiel verwendeten Tasten informiert sind. So kann Ihr Spiel die Assets aktualisieren, die auf dem Spielbildschirm angezeigt werden und mit denen die Aktionssteuerelemente dargestellt werden.
Das folgende Bild zeigt ein Beispiel für dieses Verhalten. Nachdem die Tasten

Diese Funktion wird durch die Registrierung eines InputRemappingListener-Rückrufs erreicht. Registrieren Sie zuerst eine InputRemappingListener-Instanz, um diese Funktion zu implementieren:
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
Die InputRemappingListener wird beim Start nach dem Laden der vom Nutzer gespeicherten neu zugewiesenen Steuerelemente und jedes Mal benachrichtigt, wenn der Nutzer seine Tasten neu zuweist.
Initialisierung
Wenn Sie InputContexts verwenden, müssen Sie den Kontext bei jedem Übergang zu einer neuen Szene festlegen, einschließlich des ersten Kontexts für die erste Szene. Sie müssen die InputContext festlegen, nachdem Sie Ihre InputMap registriert haben.
Wenn Sie InputRemappingListeners verwenden, um über Ereignisse zur Neuzuordnung benachrichtigt zu werden, registrieren Sie InputRemappingListener, bevor Sie InputMappingProvider registrieren. Andernfalls kann es sein, dass Ihr Spiel während der Einführung wichtige Ereignisse verpasst.
Das folgende Beispiel zeigt, wie die API initialisiert wird:
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 } }
Bereinigen
Heben Sie die Registrierung Ihrer InputMappingProvider-Instanz und aller InputRemappingListener-Instanzen auf, wenn Ihr Spiel geschlossen wird. Das Input SDK ist jedoch intelligent genug, um Ressourcenlecks zu vermeiden, wenn Sie dies nicht tun:
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
Sie können Ihre Input SDK-Implementierung testen, indem Sie das Overlay manuell öffnen, um die Player-Oberfläche aufzurufen, oder über die adb-Shell für automatisierte Tests und die Überprüfung.
Der Emulator für Google Play Games auf dem PC prüft die Richtigkeit Ihrer Eingabebelegung anhand häufiger Fehler. Bei Szenarien wie doppelten eindeutigen IDs, der Verwendung unterschiedlicher Eingabekarten oder Fehlern bei den Neuzuordnungsregeln (wenn die Neuzuordnung aktiviert ist) wird im Overlay eine Fehlermeldung wie unten angezeigt:

Überprüfen Sie Ihre Input SDK-Implementierung mit adb in der Befehlszeile.
Verwenden Sie den folgenden adb shell-Befehl, um die aktuelle Eingabebelegung abzurufen (ersetzen Sie MY.PACKAGE.NAME durch den Namen Ihres Spiels):
adb shell dumpsys input_mapping_service --get MY.PACKAGE.NAME
Wenn Sie Ihre InputMap erfolgreich registriert haben, sehen Sie eine Ausgabe wie diese:
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
}
Lokalisierung
Das Input SDK verwendet nicht das Lokalisierungssystem von Android. Daher müssen Sie lokalisierte Strings angeben, wenn Sie ein InputMap einreichen. Sie können auch das Lokalisierungssystem Ihrer Spiel-Engine verwenden.
Proguard
Wenn Sie Proguard zum Minimieren Ihres Spiels verwenden, fügen Sie der Proguard-Konfigurationsdatei die folgenden Regeln hinzu, damit das SDK nicht aus Ihrem endgültigen Paket entfernt wird:
-keep class com.google.android.libraries.play.hpe.** { *; }
-keep class com.google.android.libraries.play.games.inputmapping.** { *; }
Nächste Schritte
Nachdem Sie das Input SDK in Ihr Spiel eingebunden haben, können Sie mit den verbleibenden Anforderungen für Google Play Games auf dem PC fortfahren. Weitere Informationen finden Sie unter Erste Schritte mit Google Play Games auf dem PC.