Migrer vers les services de jeux Play v2 (Unity)

Ce document explique comment migrer des jeux existants du SDK games v1 vers le SDK games v2. Le plug-in Play Jeux pour Unity, versions 10 et antérieures, utilise le SDK v1 de Jeux.

Avant de commencer

  • Assurez-vous d'avoir déjà configuré la Play Console et installé l'éditeur Unity.

Télécharger le plug-in Google Play Jeux pour Unity

Pour bénéficier des dernières fonctionnalités des services Play Jeux, téléchargez et installez la dernière version du plug-in. Téléchargez-le depuis le dépôt GitHub.

Supprimer l'ancien plug-in

Dans l'éditeur Unity, supprimez les dossiers ou fichiers suivants.

Assets/GooglePlayGames

Assets/GeneratedLocalRepo/GooglePlayGames

Assets/Plugins/Android/GooglePlayGamesManifest.androidlib

Assets/Plugins/Android
Supprimez les dossiers mis en surbrillance dans votre projet Unity.
Supprimez les dossiers mis en surbrillance dans votre projet Unity (cliquez pour agrandir).

Importer le nouveau plug-in dans votre projet Unity

Pour importer le plug-in dans votre projet Unity, procédez comme suit :

  1. Ouvrez votre projet de jeu.
  2. Dans l'éditeur Unity, cliquez sur Assets > Import Package > Custom Package (Éléments > Importer un package > Package personnalisé) pour importer le fichier unitypackage téléchargé dans les éléments de votre projet.
  3. Assurez-vous que votre plate-forme de compilation actuelle est définie sur Android.

    1. Dans le menu principal, cliquez sur File > Build Settings (Fichier > Paramètres de compilation).

    2. Sélectionnez Android, puis cliquez sur Switch Platform (Changer de plate-forme).

    3. Vous devriez voir un nouvel élément de menu sous Window > Google Play Games (Fenêtre > Google Play Jeux). Si ce n'est pas le cas, actualisez les éléments en cliquant sur Assets > Refresh (Assets > Actualiser), puis réessayez de définir la plate-forme de compilation.

  4. Dans l'éditeur Unity, cliquez sur File > Build Settings > Player Settings > Other Settings (Fichier > Paramètres de compilation > Paramètres du lecteur > Autres paramètres).

  5. Dans la zone Target API level (Niveau d'API cible), sélectionnez une version.

  6. Dans la zone Scripting backend (Backend de script), saisissez IL2CPP.

  7. Dans la zone Target architectures (Architectures cibles), sélectionnez une valeur.

  8. Notez le nom du package package_name. Vous pourrez utiliser ces informations ultérieurement.

    Les paramètres du lecteur dans votre projet Unity
    Paramètres du lecteur dans votre projet Unity.
  9. Copier les ressources Android depuis la Play Console

  10. Ajouter les ressources Android à votre projet Unity

Chemins de migration

Le chemin de migration approprié pour votre jeu dépend de la façon dont il implémente les services de jeux Play v1 et gère l'identité des joueurs. Pour assurer une transition fluide et éviter la perte de données de joueurs, identifiez le scénario qui correspond le mieux à votre configuration existante et suivez les étapes correspondantes.

Option 1 : Pour les jeux où l'IGA est lié à l'ID de joueur des services de jeux Play

Ce scénario s'applique aux jeux qui ont utilisé Player ID des services de jeux Play comme seul identifiant pour le compte de jeu d'un joueur et qui n'ont pas précédemment demandé ni stocké d'OpenID. Le principal défi consiste à associer l'IGA existant à un identifiant principal (OpenID) sans perdre le lien avec la progression du joueur.

Le flux de migration comprend les étapes suivantes :

  1. Lorsque le jeu est lancé, le SDK des services de jeux Play v2 authentifie automatiquement et silencieusement la plate-forme.
  2. L'écran de connexion du jeu s'affiche. Cet écran doit comporter un bouton Se connecter avec Google (SiWG, Sign-in with Google) à la place du bouton Google Play. Pour intégrer :

    1. Téléchargez CredManBridge.java dans votre dossier. Cette classe Java sert de pont entre Unity et la bibliothèque androidx.credentials.

      CredManBridge.java
      
      package com.wickedcube.trivialkart;
      import android.accounts.Account;
      import android.content.Context;
      import android.util.Log;
      import android.os.CancellationSignal;
      import androidx.credentials.CredentialManager;
      import androidx.credentials.GetCredentialRequest;
      import androidx.credentials.GetCredentialResponse;
      import androidx.credentials.exceptions.GetCredentialException;
      import androidx.credentials.exceptions.NoCredentialException;
      import com.google.android.libraries.identity.googleid.GetGoogleIdOption;
      import com.google.android.libraries.identity.googleid.GoogleIdTokenCredential;
      import com.google.android.gms.auth.api.identity.AuthorizationClient;
      import com.google.android.gms.auth.api.identity.AuthorizationRequest;
      import com.google.android.gms.auth.api.identity.AuthorizationResult;
      import com.google.android.gms.common.api.ApiException;
      import com.google.android.gms.auth.api.identity.Identity;
      import com.google.android.gms.common.api.Scope;
      import com.unity3d.player.UnityPlayer;
      import java.util.Collections;
      import java.util.List;
      import java.util.concurrent.Executor;
      import java.util.concurrent.Executors;

      public class CredManBridge {

      // --- MODE 1: SILENT SIGN-IN (Called on Awake) --- // Tries to auto-select an authorized account. If it fails, it does NOT show UI. public static void signInSilent(Context context, String webClientId) { CredentialManager credentialManager = CredentialManager.create(context); CancellationSignal cancellationSignal = new CancellationSignal(); Executor executor = Executors.newSingleThreadExecutor();

      Log.d("CredMan", "Attempting Silent Sign-In...");

      GetGoogleIdOption silentOption = new GetGoogleIdOption.Builder() .setFilterByAuthorizedAccounts(true) // Strict: Only authorized accounts .setServerClientId(webClientId) .setAutoSelectEnabled(true) // Auto-select if possible .build();

      GetCredentialRequest silentRequest = new GetCredentialRequest.Builder() .addCredentialOption(silentOption) .build();

      credentialManager.getCredentialAsync( context, silentRequest, cancellationSignal, executor, new androidx.credentials.CredentialManagerCallback<GetCredentialResponse, GetCredentialException>() { @Override public void onResult(GetCredentialResponse result) { Log.d("CredMan", "Silent Sign-In Successful!"); handleSignInResult(context, result, webClientId); }

          @Override
          public void onError(GetCredentialException e) {
              // Send a specific error code so Unity knows to just stay on the Start Screen
              Log.d("CredMan", "Silent sign-in failed. Keeping UI hidden.");
              UnityPlayer.UnitySendMessage("AuthManager", "OnSignInError", "SilentFailed");
          }
      }
      

      ); }

      // --- MODE 2 : CONNEXION INTERACTIVE (appelée lors d'un clic sur un bouton) --- // Force l'affichage de la feuille de sélection de compte ou d'ajout de compte. public static void signInInteractive(Context context, String webClientId) { CredentialManager credentialManager = CredentialManager.create(context); CancellationSignal cancellationSignal = new CancellationSignal(); Executor executor = Executors.newSingleThreadExecutor();

      Log.d("CredMan", "Starting Interactive Sign-In...");

      GetGoogleIdOption interactiveOption = new GetGoogleIdOption.Builder() .setFilterByAuthorizedAccounts(false) // Show ALL accounts (and "Add Account") .setServerClientId(webClientId) .setAutoSelectEnabled(false) // Force the UI to show .build();

      GetCredentialRequest interactiveRequest = new GetCredentialRequest.Builder() .addCredentialOption(interactiveOption) .build();

      credentialManager.getCredentialAsync( context, interactiveRequest, cancellationSignal, executor, new androidx.credentials.CredentialManagerCallback<getcredentialresponse, getcredentialexception="">() { @Override public void onResult(GetCredentialResponse result) { Log.d("CredMan", "Interactive Sign-In Successful!"); handleSignInResult(context, result, webClientId); }</getcredentialresponse,>

          @Override
          public void onError(GetCredentialException e) {
              Log.e("CredMan", "Interactive Sign-In Canceled or Failed", e);
              UnityPlayer.UnitySendMessage("AuthManager", "OnSignInError", "Canceled");
          }
      }
      

      ); }

      private static void handleSignInResult(Context context, GetCredentialResponse result, String webClientId) { try { GoogleIdTokenCredential credential = GoogleIdTokenCredential.createFrom(result.getCredential().getData()); String email = credential.getId();

      Account account = new Account(email, "com.google");
      // Requesting GAMES_LITE scope to check for pre-existing V1 grants
      List<Scope> requestedScopes = Collections.singletonList(new Scope("https://www.googleapis.com/auth/games_lite"));
      
      AuthorizationRequest authRequest = new AuthorizationRequest.Builder()
          .setRequestedScopes(requestedScopes)
          .setAccount(account)
          .requestOfflineAccess(webClientId)
          .build();
      
      AuthorizationClient authClient = Identity.getAuthorizationClient(context);
      
      authClient.authorize(authRequest)
          .addOnSuccessListener(authorizationResult -> {
              if (authorizationResult.getServerAuthCode() != null) {
                  // CASE 1: RETURNING USER (Success)
                  // The user has already granted GAMES_LITE in the past.
                  // We got the code directly without showing UI.
                  Log.i("CredMan", "PGS v1: Existing grant found. Returning user detected. Auth Code retrieved.");
                  UnityPlayer.UnitySendMessage("AuthManager", "OnSignInSuccess", authorizationResult.getServerAuthCode());
              }
              else if (authorizationResult.hasResolution()) {
                  // CASE 2: NEW USER (PendingIntent)
                  // The user has NOT granted GAMES_LITE before. The API returned a PendingIntent
                  // (authorizationResult.getPendingIntent()) to show the consent screen.
                  // As per your flow, we DISCARD this intent and do not show UI.
                  Log.i("CredMan", "PGS v1: No existing grant (PendingIntent returned). This is a NEW user or they revoked access.");
                  Log.i("CredMan", "PGS v1: Discarding PendingIntent. Proceeding as New User.");
      
                  // Notify Unity that this is a "New User" so it can trigger V2 logic instead of failing
                  UnityPlayer.UnitySendMessage("AuthManager", "OnSignInError", "NewUser_NoGrant");
              }
              else {
                  // Edge Case: No code and no resolution?
                  Log.e("CredMan", "PGS v1: Authorization success but no Auth Code or Resolution returned.");
                  UnityPlayer.UnitySendMessage("AuthManager", "OnSignInError", "No Auth Code returned");
              }
          })
          .addOnFailureListener(e -> {
              // CASE 3: GENERIC FAILURE
              Log.e("CredMan", "PGS v1: Authorization failed completely.", e);
              UnityPlayer.UnitySendMessage("AuthManager", "OnSignInError", "Authorization Failed: " + e.getMessage());
          });
      

      } catch (Exception e) { UnityPlayer.UnitySendMessage("AuthManager", "OnSignInError", "Parsing Error: " + e.getMessage()); } } }

    2. Intégration de Credential Manager :

      • Utilisez GetGoogleIdOption avec setFilterByAuthorizedAccounts(true) pour les connexions silencieuses afin de ne connecter que les utilisateurs ayant déjà autorisé l'application.
      • Utilisez setFilterByAuthorizedAccounts(false) pour les connexions interactives afin de permettre aux utilisateurs de sélectionner un compte ou d'en ajouter un.
    3. Demande de champ d'application :

      • Après avoir obtenu les identifiants Google de base, il crée un AuthorizationRequest demandant le champ d'application spécifique hérité : https://www.googleapis.com/auth/games_lite.
      • Ce champ d'application est essentiel, car il accorde au serveur l'autorisation de rechercher l'ancien PlayerID de l'utilisateur.
    4. Gestion des résultats :

      • Si l'utilisateur accorde l'autorisation (ou l'a déjà accordée), le pont renvoie ServerAuthCode à Unity.
      • Si l'utilisateur n'a pas accordé l'autorisation (scénario "Nouvel utilisateur"), l'API renvoie un PendingIntent. Dans cet exemple, l'intent est supprimé et l'utilisateur est traité comme un nouvel utilisateur pour simplifier le flux.
  3. Pour prendre en charge les services Credential Manager et Google Identity, assurez-vous que les dépendances suivantes sont ajoutées à votre configuration Gradle mainTemplate.gradle.

    dependencies {
    // Standard Unity dependencies
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    
    // Credential Manager and Identity Libraries
    implementation 'androidx.credentials:credentials:1.3.0'
    implementation 'androidx.credentials:credentials-play-services-auth:1.3.0'
    implementation 'com.google.android.libraries.identity.googleid:googleid:1.1.1'
    
    // Play Services Auth for legacy scope handling
    implementation 'com.google.android.gms:play-services-auth:21.2.0'
    }
    • Credential Manager : gère l'orchestration de l'identité et l'UI pour la sélection de compte.
    • Bibliothèque GoogleID : fournit spécifiquement GetGoogleIdOption pour récupérer les jetons OpenID Connect.
    • Authentification des services Play : requise pour maintenir la compatibilité et demander le champ d'application GAMES_LITE pour la récupération de l'ancien Player ID.
  4. Lorsque le joueur appuie sur le bouton Se connecter avec Google et sélectionne un compte Google, le jeu doit récupérer deux identifiants distincts :

    • Le OpenID, identifiant principal pour l'association de l'IGA.
    • Le Player ID des services de jeux Play, récupéré à l'aide du champ d'application GAMES_LITE, pour rechercher l'IGA du joueur dans votre système de backend et effectuer l'association.
  5. Lors des lancements de jeux ultérieurs, les joueurs peuvent accéder à leur IGA via le flux SiWG, sans que les jeux aient besoin d'utiliser Player ID comme identifiant principal.

Vous pouvez effectuer l'étape 4 à l'aide d'une implémentation côté client du jeu.

  1. Le développeur appelle l'API Android Credential Manager pour connecter l'utilisateur avec un compte Google.
  2. Une fois que l'utilisateur a terminé la procédure SiwG et sélectionné un compte Google, le développeur reçoit un objet de résultat contenant le jeton d'identité et l'adresse e-mail.
  3. Le développeur construit un objet Account à partir de l'adresse e-mail.
  4. Le développeur appelle l'API Authorization avec le champ d'application GAMES_LITE et le compte.
  5. Si le compte dispose d'un accès préexistant au champ d'application GAMES_LITE, l'API Authorization renvoie un jeton directement dans l'objet de réponse.
    1. Utilisez le jeton de réponse pour appeler les serveurs des services de jeux Play et récupérer les Player ID des services de jeux Play.
    2. Le développeur vérifie si les services de jeux Play Player ID ont été associés à un compte dans le jeu.
      1. Le développeur sait qu'il s'agit d'un utilisateur connu grâce à la version 1 des services Play Games.
    3. Le développeur peut associer le nouvel ID Gaia à l'ancien compte des services de jeux Play v1.
  6. Si le compte ne dispose pas d'une autorisation préexistante pour le champ d'application GAMES_LITE, l'API Authorization renvoie une PendingIntent.
    1. Le développeur sait que l'utilisateur ne dispose pas d'un compte existant dans les services Play Games v1.
    2. Le développeur peut supprimer PendingIntent sans afficher d'UI.

Option 2 : Pour les jeux qui associent déjà IGA à OpenID

Les développeurs de ce groupe disposent du chemin de migration le plus simple. Si le compte de jeu est déjà principalement associé à l'OpenID, vous n'avez qu'à effectuer la migration technique standard du SDK de la version 1 vers la version 2, comme indiqué dans les étapes.

Mettre à jour le code de connexion automatique

Remplacez la classe d'initialisation PlayGamesClientConfiguration par la classe PlayGamesPlatform.Instance.Authenticate(). L'initialisation et l'activation de PlayGamesPlatform ne sont pas requises. L'appel de PlayGamesPlatform.Instance.Authenticate() récupère le résultat de la connexion automatique. Pour en savoir plus sur le flux d'authentification recommandé avec l'intégration des services de jeux Play v2, consultez les Consignes relatives à l'expérience utilisateur pour un flux d'authentification idéal.

C#

Dans l'éditeur Unity, recherchez les fichiers avec la classe PlayGamesClientConfiguration.

using GooglePlayGames;
using GooglePlayGames.BasicApi;
using UnityEngine.SocialPlatforms;

public void Start() {
    PlayGamesClientConfiguration config =
        new PlayGamesClientConfiguration.Builder()
    // Enables saving game progress
    .EnableSavedGames()
    // Requests the email address of the player be available
    // will bring up a prompt for consent
    .RequestEmail()
    // Requests a server auth code be generated so it can be passed to an
    // associated backend server application and exchanged for an OAuth token
    .RequestServerAuthCode(false)
    // Requests an ID token be generated. This OAuth token can be used to
    // identify the player to other services such as Firebase.
    .RequestIdToken()
    .Build();

    PlayGamesPlatform.InitializeInstance(config);
    // recommended for debugging:
    PlayGamesPlatform.DebugLogEnabled = true;
    // Activate the Google Play Games platform
    PlayGamesPlatform.Activate();
}

Apportez-lui la modification suivante :

using GooglePlayGames;

public void Start() {
    PlayGamesPlatform.Instance.Authenticate(ProcessAuthentication);
}

internal void ProcessAuthentication(SignInStatus status) {
    if (status == SignInStatus.Success) {
        // Continue with Play Games Services
    } else {
        // Disable your integration with Play Games Services or show a login
        // button to ask users to sign-in. Clicking it should call
        // PlayGamesPlatform.Instance.ManuallyAuthenticate(ProcessAuthentication).
    }
}

Choisir une plate-forme de réseau social

Pour choisir une plate-forme de réseau social, consultez Choisir une plate-forme de réseau social.

Récupérer les codes d'authentification du serveur

Pour obtenir des codes d'accès côté serveur, consultez Récupérer les codes d'authentification du serveur.

Supprimer le code de déconnexion

Supprimez le code de déconnexion. Les services de jeux Play ne nécessitent plus de bouton de déconnexion dans le jeu.

Supprimez le code indiqué dans l'exemple suivant :

C#

// sign out
PlayGamesPlatform.Instance.SignOut();

Tester votre jeu

Assurez-vous que votre jeu fonctionne comme prévu en le testant. Les tests que vous effectuez dépendent des fonctionnalités de votre jeu.

Voici une liste des tests courants à exécuter.

  1. Connexion réussie.

    1. La connexion automatique fonctionne. L'utilisateur doit être connecté aux services de jeux Play au lancement du jeu.

    2. Le pop-up de bienvenue s'affiche.

      Exemple de pop-up de bienvenue.
      Exemple de pop-up de bienvenue (cliquez pour agrandir)

    3. Les messages de journaux de réussite s'affichent. Exécutez la commande suivante dans le terminal :

      adb logcat | grep com.google.android.

      Un message de journal réussi est illustré dans l'exemple suivant :

      [$PlaylogGamesSignInAction$SignInPerformerSource@e1cdecc
      number=1 name=GAMES_SERVICE_BROKER>], returning true for shouldShowWelcomePopup.
      [CONTEXT service_id=1 ]
  2. Assurez-vous de la cohérence des composants de l'UI.

    1. Les pop-ups, les classements et les réussites s'affichent correctement et de manière cohérente sur différentes tailles et orientations d'écran dans l'interface utilisateur des services de jeux Play.

    2. L'option de déconnexion n'est pas visible dans l'UI des services Play Games.

    3. Assurez-vous de pouvoir récupérer l'ID du joueur et, le cas échéant, que les fonctionnalités côté serveur fonctionnent comme prévu.

    4. Si le jeu utilise l'authentification côté serveur, testez minutieusement le flux requestServerSideAccess. Assurez-vous que le serveur reçoit le code d'autorisation et peut l'échanger contre un jeton d'accès. Testez les scénarios de réussite et d'échec pour les erreurs réseau et les scénarios client ID non valides.

Si votre jeu utilisait l'une des fonctionnalités suivantes, testez-les pour vous assurer qu'elles fonctionnent de la même manière qu'avant la migration :

  • Classements : envoyez des scores et consultez les classements. Vérifiez que le classement, ainsi que les noms et les scores des joueurs sont corrects.
  • Succès : déverrouillez des succès et vérifiez qu'ils sont correctement enregistrés et affichés dans l'UI Play Jeux.
  • Jeux enregistrés : si le jeu utilise des jeux enregistrés, assurez-vous que l'enregistrement et le chargement de la progression fonctionnent parfaitement. Il est particulièrement important de tester cette fonctionnalité sur plusieurs appareils et après les mises à jour de l'application.

Tâches à effectuer après la migration

Effectuez les étapes suivantes après avoir migré vers le SDK v2 des services de jeux.

  1. Utiliser la signature d'application Play

  2. Créer un fichier AAB

  3. Créer une version pour les tests internes

  4. Valider vos identifiants de signature d'application