Inizia a utilizzare l'SDK Input

Questo documento descrive come configurare e visualizzare l'SDK di input in giochi che supportano Google Play Giochi su PC. Le attività includono l'aggiunta dell'SDK al gioco e generando una mappa di input, che contiene assegnazioni di azioni di gioco a input utente.

Prima di iniziare

Prima di aggiungere l'SDK di input al tuo gioco, devi supportare input della tastiera e del mouse utilizzando il motore di gioco di input di input.

L'SDK di input fornisce a Google Play Giochi su PC informazioni su quali controlli vengono utilizzati dal tuo gioco, in modo che possano essere mostrati all'utente. Può anche facoltativamente consentire la rimappatura della tastiera per gli utenti.

Ogni controllo è un InputAction (ad esempio, "J" per "Salta") e tu organizzi i tuoi InputActions in InputGroups. InputGroup potrebbe rappresentare un diverso nel gioco, ad esempio "Guida" o "A piedi" o "Menu principale". Puoi anche usa InputContexts per indicare quali gruppi sono attivi in punti diversi della al gioco.

Puoi attivare la gestione automatica della rimappatura della tastiera, ma se preferisci fornire una tua interfaccia per la rimappatura del controllo, poi disattiva Rimappatura dell'SDK di input.

Il seguente diagramma di sequenza descrive il funzionamento dell'API dell'SDK di input:

Diagramma di sequenza di un'implementazione di un gioco che chiama l'API Input SDK
e la sua interazione con il software Android
dispositivo.

Quando il tuo gioco implementa l'SDK di input, vengono visualizzati i tuoi controlli nell'overlay di Google Play Giochi su PC.

L'overlay di Google Play Giochi su PC

L'overlay di Google Play Giochi su PC ("overlay") mostra i controlli definiti dal tuo gioco. Gli utenti possono accedere all'overlay in qualsiasi momento premendo Maiusc + Tab.

L'overlay di Google Play Giochi su PC.

Best practice per la progettazione di associazioni di chiavi

Quando progetti le associazioni di chiavi, tieni presente le seguenti best practice:

  • Raggruppa InputActions in InputGroups correlati logicamente per migliorare navigazione e rilevabilità dei controlli durante il gameplay.
  • Assegna ogni InputGroup a un massimo di un InputContext. Granulare InputMap offre un'esperienza migliore per la navigazione nei controlli in l'overlay.
  • Crea un elemento InputContext per ogni tipo di scena del gioco. In genere, puoi utilizzare un singolo InputContext per tutte le categorie di menu scene di gioco. Usa InputContexts diversi per ogni minigiochi nel tuo gioco o per controlli alternativi per una singola scena.
  • Se due azioni sono progettate per utilizzare la stessa chiave nella stessa InputContext, utilizza la stringa di etichetta, ad esempio "Interagisci / Attiva".
  • Se due tasti sono progettati per essere associati allo stesso InputAction, usa 2 InputActions diversi che eseguono la stessa azione nel gioco. Puoi utilizza la stessa stringa di etichetta per InputActions, ma il suo ID deve essere diverso.
  • Se viene applicato un tasto di modifica a un insieme di tasti, considera l'idea di avere un solo tasto InputAction con il tasto di modifica anziché più InputActions che combina il tasto di modifica (ad es. usa Maiusc e W, A, S, D) Maiusc + W, Maiusc + A, Maiusc + S, Maiusc + D).
  • La rimappatura dell'input viene disattivata automaticamente quando l'utente scrive nel testo campi. Segui le best practice per l'implementazione dei campi di testo Android per assicurarti Android può rilevare i campi di testo nel tuo gioco e impedire la rimappatura dei tasti. di interferire con essi. Se il tuo gioco deve utilizzare testo non convenzionale campi che puoi usare setInputContext() con un InputContext contenente un elenco vuoto di InputGroups per disattivare manualmente la rimappatura.
  • Se il tuo gioco supporta la rimappatura, valuta la possibilità di aggiornare le associazioni di tasti per un'operazione sensibile che può essere in conflitto con le versioni salvate dall'utente. Evita e modificare gli ID dei controlli esistenti, se possibile.

La funzionalità di rimappatura

Google Play Giochi su PC supporta la rimappatura dei controlli da tastiera in base al tasto associazioni fornite dal gioco mediante l'SDK di input. Questa opzione è facoltativa e possono essere completamente disattivati. Ad esempio, potresti voler fornire la tua tastiera per la rimappatura. Per disattivare la rimappatura per il tuo gioco, devi solo specificare l'opzione di rimappatura disattivata per InputMap (consulta crea una mappa di input per ulteriori informazioni).

Per accedere a questa funzione gli utenti devono aprire l'overlay e fare clic sull'azione che vogliono rimappare. Dopo ogni evento di rimappatura, le mappe di Google Play Giochi su PC ogni controllo rimappato dall'utente ai controlli predefiniti che il gioco si aspetta ricevere, quindi non è necessario che il giocatore sia a conoscenza della rimappatura del giocatore. Tu facoltativamente, puoi aggiornare gli asset utilizzati per visualizzare i controlli da tastiera al gioco aggiungendo un callback per gli eventi di rimappatura.

Prova a rimappare la chiave

Google Play Giochi su PC memorizza localmente i controlli rimappati per ogni utente, e abilitare la persistenza di controllo tra le sessioni di gioco. Queste informazioni vengono memorizzate su disco solo per la piattaforma PC e non influisce sull'esperienza mobile. I dati di controllo vengono eliminati quando l'utente disinstalla o reinstalla Google Play Giochi su PC. Questi dati non sono permanenti tra più PC.

Per supportare la funzionalità di rimappatura nel tuo gioco, evita le seguenti limitazioni:

Limitazioni della rimappatura

Puoi disattivare le funzionalità di rimappatura nel gioco se le associazioni di tasti contengono una qualsiasi dei seguenti casi:

  • InputActions con più tasti e non composti da un tasto di modifica + A non modificato. Ad esempio, Maiusc + A è valido ma A + B, Ctrl + Alt o Maiusc + A + Tab non lo sono.
  • InputMap contiene InputActions, InputGroups o InputContexts con ID univoci ripetuti.
di Gemini Advanced.

Limiti della rimappatura

Quando progetti le associazioni di tasti per la rimappatura, tieni presente quanto segue limitazioni:

  • La rimappatura alle combinazioni di tasti non è supportata. Ad esempio, gli utenti non possono rimappa Maiusc + A a Ctrl + B o A a Maiusc + A.
  • La rimappatura non è supportata per InputActions con pulsanti del mouse. Per Ad esempio, Maiusc + Clic con il tasto destro del mouse non può essere rimappato.

Testa la rimappatura dei tasti nell'emulatore di Google Play Giochi su PC

Puoi attivare la funzionalità di rimappatura nell'emulatore di Google Play Giochi su PC in qualsiasi momento utilizzando il seguente comando adb:

adb shell dumpsys input_mapping_service --set RemappingFlagValue true

L'overlay cambia come nell'immagine seguente:

L'overlay con rimappatura dei tasti attivata.

Aggiungi l'SDK

Installa l'SDK di input in base alla tua piattaforma di sviluppo.

Java e Kotlin

Ottieni l'SDK di input per Java o Kotlin aggiungendo una dipendenza al tuo file build.gradle a livello di modulo:

dependencies {
  implementation 'com.google.android.libraries.play.games:inputmapping:1.1.0-beta'
  ...
}

Unity

L'SDK di input è un pacchetto Unity standard con diverse dipendenze.

È richiesta l'installazione del pacchetto con tutte le dipendenze. Ci sono diversi modi per installare i pacchetti.

Installa .unitypackage

Scarica il file unitypackage dell'SDK di input con tutte le sue dipendenze. Puoi installare .unitypackage selezionando Asset > Importa pacchetto > pacchetto personalizzato e individua il file scaricato.

Installa tramite UPM

In alternativa, puoi installare il pacchetto utilizzando il comando Gestore pacchetti di Unity di scarica .tgz e installa le relative dipendenze:

Installa tramite OpenUPM

Puoi installare il pacchetto utilizzando OpenUPM

$ openupm add com.google.android.libraries.play.games.inputmapping

Giochi di esempio

Per esempi di come eseguire l'integrazione con l'SDK di input, vedi Tunnel AGDK per i giochi Kotlin o Java e Trivial Kart per i giochi Unity.

Generare le associazioni di chiavi

Registra le associazioni di chiavi creando un InputMap e restituendolo con un InputMappingProvider. L'esempio seguente illustra un 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

Definisci le azioni di input

La classe InputAction viene utilizzata per mappare una chiave o una combinazione di tasti a un gioco un'azione. InputActions deve avere ID univoci in tutti gli attributi InputActions.

Se supporti la rimappatura, puoi definire cosa può essere InputActions rimappato. Se il tuo gioco non supporta la rimappatura, devi impostarla disabilitata per tutti i tuoi InputActions, ma l'SDK di input è abbastanza intelligenti da disattivare la rimappatura se non la supporti InputMap.

In questo esempio la chiave spazio viene mappata sull'azione Drive.

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
);

InputAction del tasto singolo visualizzato nell&#39;overlay.

Le azioni possono anche rappresentare gli input del mouse. In questo esempio il Clic con il tasto sinistro viene impostato su l'azione Sposta:

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
);

Mouse InputAction visualizzato nell&#39;overlay.

Le combinazioni di tasti vengono specificate trasmettendo più codici chiave al tuo InputAction. In questo esempio, spazio + Maiusc è mappato a l'azione Turbo, che funziona anche quando lo Spazio è mappato a Drive.

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
);

InputAction con più tasti visualizzato nell&#39;overlay.

L'SDK di input ti consente di combinare i pulsanti del mouse e dei tasti per ottenere una singola azione. Questo esempio indica che le opzioni Maiusc e Clic con il tasto destro del mouse se si preme insieme si aggiunge un waypoint in questo gioco di esempio:

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
);

Combinazione di tasto + mouse InputAction visualizzata nell&#39;overlay.

InputAction contiene i seguenti campi:

  • ActionLabel: la stringa visualizzata nella UI per rappresentare questa azione. La localizzazione non viene eseguita automaticamente, quindi devi eseguire qualsiasi in primo piano.
  • InputControls: definisce i controlli di input utilizzati da questa azione. La i controlli vengono mappati a glifi coerenti nell'overlay.
  • InputActionId: oggetto InputIdentifier in cui sono archiviati l'ID numero e la versione di InputAction (consulta gli ID delle chiavi di monitoraggio per informazioni).
  • InputRemappingOption: uno tra InputEnums.REMAP_OPTION_ENABLED o InputEnums.REMAP_OPTION_DISABLED. Definisce se l'azione è abilitata su rimappa. Se il tuo gioco non supporta la rimappatura, puoi saltare questo campo oppure è sufficiente disabilitarla.
  • RemappedInputControls: oggetto InputControls di sola lettura utilizzato per leggere l'elemento tasto rimappato impostato dall'utente negli eventi di rimappatura (utilizzato per ricevere notifiche sugli eventi di rimappatura).

InputControls rappresenta gli input associati a un'azione e contiene i parametri seguenti campi:

  • AndroidKeycodes: è un elenco di numeri interi che rappresentano gli input da tastiera associati a un'azione. Questi sono definiti nel KeyEvent o la classe AndroidKeycode per Unity.
  • MouseActions: è un elenco di MouseAction valori che rappresentano gli input del mouse associati a questa azione.

Definisci i gruppi di input

Le azioni InputActions vengono raggruppate con azioni correlate logicamente utilizzando InputGroups per migliorare la navigazione e la rilevabilità dei controlli nell'overlay. Ciascuna L'ID InputGroup deve essere univoco per tutti i InputGroups del gioco.

Organizzando le azioni di input in gruppi, per un giocatore sarà più facile a trovare l'associazione di tasti corretta per il contesto attuale.

Se supporti la rimappatura, puoi definire cosa può essere InputGroups rimappato. Se il tuo gioco non supporta la rimappatura, devi impostarla disabilitata per tutti i tuoi InputGroups, ma l'SDK di input è abbastanza intelligenti da disattivare la rimappatura se non la supporti 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
);

L'esempio seguente mostra i Controlli stradali e i Controlli di menu. gruppi di input nell'overlay:

L&#39;overlay che mostra una InputMap contenente i controlli Road e
Il menu controlla i gruppi di input.

InputGroup contiene i seguenti campi:

  • GroupLabel: una stringa da visualizzare nell'overlay che può essere utilizzata per raggruppare logicamente un insieme di azioni. Questa stringa non viene automaticamente localizzato.
  • InputActions: un elenco di InputAction oggetti definiti nella precedente passaggio. Tutte queste azioni vengono visualizzate visivamente sotto l'intestazione del gruppo.
  • InputGroupId: l'oggetto InputIdentifier in cui sono archiviati l'ID numero e di InputGroup. Consulta ID chiave di monitoraggio per ulteriori informazioni.
  • InputRemappingOption: uno tra InputEnums.REMAP_OPTION_ENABLED o InputEnums.REMAP_OPTION_DISABLED. Se disattivata, tutti i InputAction la rimappatura degli oggetti appartenenti a questo gruppo verrà disattivata anche se e specificare se è attivata l'opzione di rimappatura. Se attivata, tutte le azioni appartenenti a questo gruppo può essere rimappabile, a meno che non sia specificato disabilitato dal singolo azioni.
di Gemini Advanced.

Definisci i contesti di input

InputContexts consente al tuo gioco di utilizzare un insieme diverso di controlli da tastiera per diverse scene del gioco. Ad esempio:

  • Puoi specificare set di input diversi per la navigazione nei menu e per lo spostamento nel gioco.
  • Puoi specificare diversi insiemi di input a seconda della modalità di locomozione nel tuo gioco, ad esempio guidare rispetto a camminare.
  • Puoi specificare diversi set di input in base allo stato attuale come navigare in un overworld invece di giocare a un livello individuale.

Quando utilizzi InputContexts, l'overlay mostra prima i gruppi del contesto in uso. Per attivare questo comportamento, chiama setInputContext() e imposta il contesto ogni volta che il gioco entra in una scena diversa. L'immagine seguente dimostra questo comportamento: nella fase di "guida" scena, la sezione Controlli stradali sono visualizzate nella parte superiore dell'overlay. Quando apri il "negozio" il menu "Controlli del menu" le azioni sono visualizzate nella parte superiore dell'overlay.

InputContexts: ordinamento dei gruppi nell&#39;overlay.

Questi aggiornamenti dell'overlay vengono eseguiti impostando un InputContext diverso a diversi punti nel gioco. Per:

  1. Raggruppa InputActions con azioni correlate logicamente utilizzando InputGroups
  2. Assegna questi InputGroups a un InputContext per le diverse parti di il tuo gioco

InputGroups che appartengono agli stessiInputContextnon possono avere conflitti InputActions dove viene utilizzata la stessa chiave. È buona prassi assegnare ogni InputGroup a un singolo InputContext.

Il seguente codice di esempio illustra la logica 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 contiene i seguenti campi:

  • LocalizedContextLabel: una stringa che descrive i gruppi appartenenti al contesto.
  • InputContextId: oggetto InputIdentifier in cui sono archiviati l'ID numero e la versione di InputContext (consulta gli ID delle chiavi di monitoraggio per informazioni).
  • ActiveGroups: un elenco di InputGroups da utilizzare e visualizzare in alto dell'overlay quando questo contesto è attivo.

Crea una mappa di input

InputMap è una raccolta di tutti gli oggetti InputGroup disponibili in un e quindi tutti gli oggetti InputAction che un giocatore può aspettarsi eseguire il deployment.

Quando segnali le associazioni di chiavi, crei un InputMap con tutte le InputGroups usati nel tuo gioco.

Se il tuo gioco non supporta la rimappatura, imposta l'opzione di rimappatura disattivata e le chiavi riservate sono vuote.

L'esempio seguente crea un InputMap utilizzato per segnalare una raccolta di 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 contiene i seguenti campi:

  • InputGroups: i gruppi di input segnalati dal tuo gioco. I gruppi sono visualizzati in ordine nell'overlay, a meno che non siano specificati i gruppi correnti in chiama setInputContext().
  • MouseSettings: l'oggetto MouseSettings indica che la sensibilità del mouse e che il mouse sia invertito sull'asse Y.
  • InputMapId: oggetto InputIdentifier in cui sono archiviati l'ID numero e la versione di InputMap (consulta ID chiave di monitoraggio per ulteriori informazioni).
  • InputRemappingOption: uno tra InputEnums.REMAP_OPTION_ENABLED o InputEnums.REMAP_OPTION_DISABLED. Definisce se la funzionalità di rimappatura è in un bucket con il controllo delle versioni attivo.
  • ReservedControls: un elenco di InputControls a cui gli utenti non sono autorizzati rimappare.

ID chiave di monitoraggio

Gli oggetti InputAction, InputGroup, InputContext e InputMap contengono un'etichetta Oggetto InputIdentifier che memorizza un ID numero univoco e un ID versione stringa. Il monitoraggio della versione stringa degli oggetti è facoltativo, ma si consiglia di monitorare le versioni del tuo InputMap. Se la versione stringa non viene fornita, la stringa è vuota. La versione della stringa è obbligatoria per gli oggetti InputMap.

L'esempio seguente assegna una versione stringa a InputActions o 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

Gli ID numero di oggetti InputAction devono essere univoci in tutti gli elementi InputActions in il tuo InputMap. Allo stesso modo, InputGroup ID oggetto deve essere univoco in tutti InputGroups in InputMap. L'esempio seguente mostra come utilizzare un enum per monitorare gli ID univoci del tuo oggetto:

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 contiene i seguenti campi:

  • UniqueId: un ID numero univoco impostato per identificare chiaramente un determinato insieme di input in modo univoco.
  • VersionString: una stringa di versione leggibile impostata per identificare una versione di dati di input tra due versioni delle modifiche dei dati di input.

(Facoltativo) Ricevi notifiche sugli eventi di rimappatura

Ricevere notifiche sugli eventi di rimappatura per essere informati dei tasti in uso il tuo gioco. In questo modo il tuo gioco potrà aggiornare le risorse mostrate nella schermata del gioco utilizzata per visualizzare i controlli di azione.

L'immagine seguente mostra un esempio di questo comportamento in cui dopo la rimappatura del tasti da G, P e da S a J, X e T, rispettivamente, gli elementi UI del gioco vengono aggiornati per visualizzare i tasti impostati dall'utente.

UI che reagisce agli eventi di rimappatura utilizzando il callback InputRemappingListener.

Questa funzionalità si ottiene registrando un InputRemappingListener di Google. Per implementare questa funzionalità, inizia registrando un Istanza 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 viene avvisato al momento del lancio dopo il caricamento controlli rimappati salvati dall'utente e dopo ogni volta che l'utente mappa nuovamente le chiavi.

Inizializzazione

Se utilizzi InputContexts, imposta il contesto su ogni passare a una nuova scena, incluso il primo contesto utilizzato per la configurazione iniziale scena. Devi impostare InputContext dopo aver registrato il tuo InputMap.

Se utilizzi InputRemappingListeners per ricevere notifiche sugli eventi relativi alla rimappatura registra il tuo InputRemappingListener prima di registrare il tuo InputMappingProvider, altrimenti la tua partita può perdere eventi importanti durante l'ora del lancio.

L'esempio seguente mostra come inizializzare l'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
    }
}

Pulizia

Annulla la registrazione dell'istanza InputMappingProvider e di eventuali InputRemappingListener di istanze in cui il gioco è chiuso, anche se l'SDK di input è intelligente in modo da evitare fughe di risorse, se non esegui queste operazioni:

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

Puoi testare l'implementazione dell'SDK di input aprendo manualmente L'overlay per visualizzare l'esperienza del player o tramite la shell ADB per le verifiche e i test automatici.

L'emulatore Google Play Giochi su PC verifica la correttezza della mappa di input contro errori comuni. Per scenari come ID univoci duplicati, l'utilizzo di mappe di input o errori nelle regole di rimappatura (se la rimappatura è attivata), di testo mostra il seguente messaggio di errore: L&#39;overlay SDK di input.

Verifica l'implementazione dell'SDK di input utilizzando adb nella riga di comando. Per ottenere la mappa di input corrente, usa il seguente comando adb shell (sostituisci MY.PACKAGE.NAME con il nome del tuo gioco):

adb shell dumpsys input_mapping_service --get MY.PACKAGE.NAME

Se la registrazione del tuo account è riuscita, vedrai un output simile a questo: InputMap:

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
}

Localizzazione

L'SDK di input non utilizza il sistema di localizzazione di Android. Come devi fornire stringhe localizzate quando invii un InputMap. Tu potrebbe anche utilizzare il sistema di localizzazione del tuo motore grafico.

ProGuard

Quando utilizzi ProGuard per minimizzare il gioco, aggiungi le seguenti regole di configurazione di ProGuard per assicurarti che l'SDK non venga rimosso dal tuo pacchetto finale:

-keep class com.google.android.libraries.play.hpe.** { *; }
-keep class com.google.android.libraries.play.games.inputmapping.** { *; }

Passaggio successivo

Dopo aver integrato l'SDK di input nel tuo gioco, puoi continuare con eventuali requisiti rimanenti di Google Play Giochi su PC. Per ulteriori informazioni, consulta la pagina Iniziare a utilizzare Google Play Giochi su PC.