Migra a la versión 2 de los Servicios de juego de Play (Unity)

En este documento, se describe cómo migrar juegos existentes del SDK de games v1 al SDK de games v2. El complemento de Play Juegos para Unity, versiones 10 y anteriores, usa el SDK de games v1.

Antes de comenzar

  • Asegúrate de haber configurado Play Console y de haber instalado Unity Editor.

Descarga el complemento de Google Play Juegos para Unity

Para aprovechar las funciones más recientes de los Servicios de Play Games, descarga e instala la versión más reciente del complemento. Descárgalo desde el gitHub repositorio.

Quita el complemento anterior

En Unity Editor, quita las siguientes carpetas o archivos.

Assets/GooglePlayGames

Assets/GeneratedLocalRepo/GooglePlayGames

Assets/Plugins/Android/GooglePlayGamesManifest.androidlib

Assets/Plugins/Android
Quita las carpetas destacadas de tu proyecto de Unity.
Quita las carpetas destacadas de tu proyecto de Unity (haz clic para ampliar).

Importa el complemento nuevo a tu proyecto de Unity

Para importar el complemento a tu proyecto de Unity, sigue estos pasos:

  1. Abre el proyecto de juego.
  2. En Unity Editor, haz clic en Assets > Import Package > Custom Package para importar el archivo unitypackage a los elementos de tu proyecto.
  3. Asegúrate de que tu plataforma de compilación actual esté configurada como Android.

    1. En el menú principal, haz clic en Archivo > Build Settings.

    2. Selecciona Android y haz clic en Switch Platform.

    3. Deberías ver un nuevo elemento de menú en Window > Google Play Juegos. Si no existe, haz clic en Recursos > Actualizar para actualizar los elementos y, luego, intenta configurar la plataforma de compilación nuevamente.

  4. En Unity Editor, haz clic en File > Build Settings > Player Settings > Other Settings.

  5. En el cuadro nivel de API objetivo, selecciona una versión.

  6. En el cuadro Scripting backend, ingresa IL2CPP.

  7. En el cuadro Target architectures, selecciona un valor.

  8. Ten en cuenta el nombre del paquete package_name.Puedes usar esta información más adelante.

    La configuración del reproductor en tu proyecto de Unity
    La configuración del reproductor en tu proyecto de Unity.
  9. Copia los recursos de Android desde Play Console

  10. Agrega los recursos de Android a tu proyecto de Unity

Rutas de migración

La ruta de migración correcta para tu juego depende de cómo implemente los Servicios de Play Games v1 y controle la identidad del jugador. Para garantizar una transición sin problemas y evitar la pérdida de datos del jugador, identifica la situación que mejor se adapte a tu configuración existente y sigue los pasos correspondientes.

Opción 1: Para juegos en los que IGA está vinculado al ID de jugador de los Servicios de juego de Play

Esta situación se aplica a los juegos que usaron los Servicios de Play Games Player ID como el único identificador para la cuenta en el juego (IGA) de un jugador y que no solicitaron ni almacenaron un OpenID anteriormente. El desafío principal es vincular la IGA existente a un identificador principal (el OpenID) sin perder la conexión con el progreso del jugador.

El flujo de migración incluye los siguientes pasos:

  1. Cuando se inicia el juego, el SDK de los Servicios de Play Games v2 autentica la plataforma de forma automática y silenciosa.
  2. El juego presenta su pantalla de acceso. Esta pantalla debe incluir un botón Acceder con Google (SiWG) , que reemplaza el botón Google Play. Para realizar la integración, haz lo siguiente:

    1. Descarga CredManBridge.java en tu carpeta. Esta clase de Java actúa como un puente entre Unity y la biblioteca 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: INTERACTIVE SIGN-IN (Called on Button Click) --- // Forces the Account Selection / "Add Account" sheet to appear. 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. Integración de Credential Manager:

      • Usa GetGoogleIdOption con setFilterByAuthorizedAccounts(true) para accesos silenciosos y solo acceder a los usuarios que autorizaron la app anteriormente.
      • Usa setFilterByAuthorizedAccounts(false) para accesos interactivos y permitir que los usuarios seleccionen una cuenta o agreguen una nueva.
    3. Solicitud de alcance:

      • Después de obtener la credencial base de Google, se crea un AuthorizationRequest que solicita el alcance heredado específico: https://www.googleapis.com/auth/games_lite.
      • Este alcance es fundamental, ya que otorga al servidor permiso para buscar el PlayerID heredado del usuario.
    4. Control de resultados:

      • Si el usuario otorga permiso (o lo otorgó anteriormente), el puente devuelve el ServerAuthCode a Unity.
      • Si el usuario no otorgó permiso (situación de usuario nuevo), la API devuelve un PendingIntent. En este ejemplo, se descarta el intent y el usuario se trata como un usuario nuevo para simplificar el flujo.
  3. Para admitir los servicios de Credential Manager y Google Identity, asegúrate de que se agreguen las siguientes dependencias a tu configuración de 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: Controla la organización de la identidad principal y la IU para la selección de cuentas.
    • Biblioteca de GoogleID: Proporciona específicamente GetGoogleIdOption para recuperar tokens de OpenID Connect.
    • Autenticación de Servicios de Play: Es necesario para mantener la compatibilidad y solicitar el alcance GAMES_LITE para la recuperación heredada de Player ID.
  4. Cuando el jugador presiona el botón SiWG y selecciona una Cuenta de Google, el juego debe recuperar dos identificadores distintos:

    • El OpenID, el identificador principal para vincular la IGA.
    • El Player ID de los Servicios de Play Games, que se recupera con el permiso GAMES_LITE, para buscar la IGA del jugador en tu sistema de backend y realizar la vinculación.
  5. En los lanzamientos posteriores del juego, los jugadores pueden acceder a su IGA a través del flujo de SiWG, sin necesidad de que los juegos usen Player ID como identificador principal.

Puedes realizar el paso 4 con una implementación del cliente del juego.

  1. El desarrollador llama a la API de Credential Manager de Android para acceder al usuario con una Cuenta de Google.
  2. Después de que el usuario completa SiwG y selecciona una Cuenta de Google, el desarrollador recibe un objeto de resultado que contiene el token de ID y la dirección de correo electrónico.
  3. El desarrollador construye un objeto de cuenta a partir de la dirección de correo electrónico.
  4. El desarrollador llama a la API de Authorization con el alcance GAMES_LITE y la cuenta.
  5. Si la cuenta tiene una concesión preexistente en el alcance GAMES_LITE, la API de Authorization devuelve un token directamente en el objeto de respuesta.
    1. Usa el token de respuesta para llamar a los servidores de los Servicios de Play Games y recuperar el Player ID de los Servicios de Play Games.
    2. El desarrollador verifica si los Servicios de Play Games Player ID se vincularon con una cuenta en el juego.
      1. El desarrollador sabe que se trata de un usuario recurrente de los Servicios de Play Games v1.
    3. El desarrollador puede vincular el nuevo ID de Gaia con la cuenta anterior de los Servicios de Play Games v1.
  6. O bien, si la cuenta no tiene una concesión preexistente en el alcance GAMES_LITE, la API de Authorization devuelve un PendingIntent.
    1. El desarrollador sabe que el usuario no tiene una cuenta existente de los Servicios de Play Games v1.
    2. El desarrollador puede descartar de forma segura el PendingIntent sin mostrar ninguna IU.

Opción 2: Para juegos que ya vinculan IGA a OpenID

Los desarrolladores de este grupo tienen la ruta de migración más sencilla. Si la cuenta en el juego de tu juego ya está vinculada principalmente al OpenID, solo debes realizar la migración estándar del SDK técnico de v1 a v2, como se describe en los pasos.

Actualiza el código de acceso automático

Reemplaza la clase de inicialización PlayGamesClientConfiguration por la clase PlayGamesPlatform.Instance.Authenticate(). No se requiere la inicialización ni la activación de PlayGamesPlatform. La llamada a PlayGamesPlatform.Instance.Authenticate() recupera el resultado del acceso automático. Para obtener más información sobre el flujo de autenticación recomendado con la integración de los Servicios de Play Games v2, consulta la guía de experiencia del usuario para el flujo de autenticación ideal.

C#

En Unity Editor, busca los archivos con la clase 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();
}

Y actualízala a lo siguiente:

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).
    }
}

Cómo elegir una plataforma social

Para elegir una plataforma social, consulta cómo elegir una plataforma social.

Recupera los códigos de autenticación del servidor

Para obtener códigos de acceso del servidor, consulta cómo recuperar los códigos de autenticación del servidor.

Quita el código de salida

Quita el código de salida. Los Servicios de Play Games ya no requieren un botón de salida en el juego.

Quita el código que se muestra en el siguiente ejemplo:

C#

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

Cómo probar tu juego

Para asegurarte de que tu juego funcione según lo diseñado, pruébalo. Las pruebas que realices dependerán de las funciones del juego.

A continuación, se incluye una lista de pruebas comunes que se deben ejecutar.

  1. Acceso correcto.

    1. El acceso automático funciona. El usuario debe acceder a los Servicios de Play Games cuando inicie el juego.

    2. Se muestra la ventana emergente de bienvenida.

      Ventana emergente de bienvenida de ejemplo.
      Ejemplo de ventana emergente de bienvenida (haz clic para ampliar).

    3. Se muestran los mensajes de registro correctos. Ejecuta el siguiente comando en la terminal:

      adb logcat | grep com.google.android.

      En el siguiente ejemplo, se muestra un mensaje de registro correcto:

      [$PlaylogGamesSignInAction$SignInPerformerSource@e1cdecc
      number=1 name=GAMES_SERVICE_BROKER>], returning true for shouldShowWelcomePopup.
      [CONTEXT service_id=1 ]
  2. Asegúrate de que los componentes de la IU sean coherentes.

    1. Las ventanas emergentes, las tablas de clasificación y los logros se muestran de forma correcta y coherente en varios tamaños y orientaciones de pantalla en la interfaz de usuario (IU) de los Servicios de Play Games.

    2. La opción de salida no está visible en la IU de los Servicios de Play Games.

    3. Asegúrate de poder recuperar el ID de jugador correctamente y, si corresponde, de que las capacidades del servidor funcionen según lo previsto.

    4. Si el juego usa la autenticación del servidor, prueba minuciosamente el flujo requestServerSideAccess. Asegúrate de que el servidor reciba el código de autenticación y pueda intercambiarlo por un token de acceso. Prueba las situaciones de éxito y de error para los errores de red y las situaciones de client ID no válidas.

Si tu juego usaba alguna de las siguientes funciones, pruébalas para asegurarte de que funcionen igual que antes de la migración:

  • Tablas de clasificación: Envía puntuaciones y consulta las tablas de clasificación. Verifica la clasificación correcta y la visualización de los nombres y las puntuaciones de los jugadores.
  • Logros: Desbloquea logros y verifica que se registren correctamente y se muestren en la IU de Play Juegos.
  • Juegos guardados: Si el juego usa juegos guardados, asegúrate de que guardar y cargar el progreso del juego funcione sin problemas. Esto es especialmente importante para probar en varios dispositivos y después de las actualizaciones de la app.

Tareas posteriores a la migración

Completa los siguientes pasos después de migrar al SDK de games v2.

  1. Usa la firma de apps de Play

  2. Crea un archivo AAB

  3. Crea una versión de prueba interna

  4. Verifica tus credenciales de firma de apps