Migrar para os serviços relacionados a jogos do Google Play v2 (Unity)

Este documento descreve como migrar jogos do games v1 SDK para o games v2 SDK. O plug-in do Play Games para Unity, versões 10 e anteriores, usa o SDK games v1.

Antes de começar

  • Verifique se você já configurou o Play Console e instalou o Unity Editor.

Baixar o plug-in do Google Play Games para Unity

Para aproveitar os recursos mais recentes dos serviços do Google Play Games, baixe e instale a versão mais recente do plug-in. Faça o download no repositório do GitHub.

Remover o plug-in antigo

No Unity Editor, remova as seguintes pastas ou arquivos:

Assets/GooglePlayGames

Assets/GeneratedLocalRepo/GooglePlayGames

Assets/Plugins/Android/GooglePlayGamesManifest.androidlib

Assets/Plugins/Android
Remova as pastas destacadas no projeto do Unity.
Remova as pastas destacadas no seu projeto do Unity (clique para ampliar).

Importe o novo plug-in para seu projeto do Unity.

Para importar o plug-in para seu projeto do Unity, siga estas etapas:

  1. Abra o projeto de jogo.
  2. No editor do Unity, clique em Assets > Import Package > Custom Package para importar o arquivo unitypackage baixado para os recursos do projeto.
  3. Confira se a plataforma de build atual está definida como Android.

    1. No menu principal, clique em Arquivo > Configurações de build.

    2. Selecione Android e clique em Switch Platform.

    3. Um novo item de menu vai aparecer em Window > Google Play Games. Se isso não acontecer, clique em Assets > Refresh para atualizar os recursos e tente definir a plataforma de build novamente.

  4. No editor do Unity, clique em File > Build Settings > Player Settings > Other Settings.

  5. Na caixa nível desejado da API, selecione uma versão.

  6. Na caixa Backend de script, insira IL2CPP.

  7. Na caixa Arquiteturas de destino, selecione um valor.

  8. Observe o nome do pacote package_name.Você pode usar essas informações mais tarde.

    As configurações do player no seu projeto do Unity
    As configurações do player no seu projeto do Unity.
  9. Copiar os recursos do Android do Play Console

  10. Adicione os recursos do Android ao seu projeto do Unity

Caminhos de migração

O caminho de migração correto para seu jogo depende de como ele implementa os serviços do Google Play Games v1 e processa a identidade do jogador. Para garantir uma transição tranquila e evitar a perda de dados dos jogadores, identifique o cenário que melhor corresponde à sua configuração atual e siga as etapas correspondentes.

Opção 1: para jogos em que a IGA está vinculada ao ID do jogador dos serviços do Google Play Games

Esse cenário se aplica a jogos que usaram os Player ID serviços do Google Play Games como o único identificador de uma conta no jogo (IGA, na sigla em inglês) de um jogador e não solicitaram nem armazenaram um OpenID antes. O principal desafio é vincular o IGA atual a um identificador principal (o OpenID) sem perder a conexão com o progresso do jogador.

O fluxo de migração inclui as seguintes etapas:

  1. Quando o jogo é iniciado, o SDK dos serviços do Google Play Games v2 autentica a plataforma de forma automática e silenciosa.
  2. O jogo mostra a tela de login. Essa tela precisa ter um botão Fazer login com o Google (SiWG) em vez do botão Google Play. Para integrar:

    1. Faça o download de CredManBridge.java na sua pasta. Essa classe Java funciona como uma ponte entre o Unity e a 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. Integração do Credential Manager:

      • Use GetGoogleIdOption com setFilterByAuthorizedAccounts(true) para fazer logins silenciosos apenas de usuários que já autorizaram o app.
      • Use setFilterByAuthorizedAccounts(false) para logins interativos e permita que os usuários selecionem uma conta ou adicionem uma nova.
    3. Solicitação de escopo:

      • Depois de receber a credencial base do Google, ela cria um AuthorizationRequest solicitando o escopo legado específico: https://www.googleapis.com/auth/games_lite.
      • Esse escopo é fundamental porque concede ao servidor permissão para pesquisar o PlayerID legado do usuário.
    4. Tratamento de resultados:

      • Se o usuário conceder permissão (ou já tiver concedido), a ponte vai retornar o ServerAuthCode para o Unity.
      • Se o usuário não tiver concedido permissão (cenário de novo usuário), a API retornará um PendingIntent. Neste exemplo, a intent é descartada, e o usuário é tratado como um novo usuário para simplificar o fluxo.
  3. Para oferecer suporte ao Credential Manager e aos serviços de identidade do Google, verifique se as seguintes dependências foram adicionadas à configuração mainTemplate.gradle do 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:processa a orquestração de identidade principal e a interface do usuário para seleção de contas.
    • Biblioteca GoogleID:fornece especificamente GetGoogleIdOption para recuperar tokens do OpenID Connect.
    • Autenticação do Google Play Services:necessária para manter a compatibilidade e solicitar o escopo GAMES_LITE para recuperação legada de Player ID.
  4. Quando o jogador toca no botão SiWG e seleciona uma Conta do Google, o jogo precisa recuperar dois identificadores distintos:

    • O OpenID, o identificador principal para vincular a IGA.
    • O Player ID dos serviços do Google Play Games, recuperado usando o escopo GAMES_LITE, para pesquisar o IGA do jogador no sistema de back-end e realizar a vinculação.
  5. Em lançamentos de jogos subsequentes, os jogadores podem acessar o IGA pelo fluxo SiWG, sem exigir que os jogos usem Player ID como um identificador principal.

Você pode realizar a etapa 4 usando uma implementação do lado do cliente do jogo.

  1. O desenvolvedor chama a API Android Credential Manager para fazer login do usuário com uma Conta do Google.
  2. Depois que o usuário concluir o SiwG e selecionar uma Conta do Google, o desenvolvedor vai receber um objeto de resultado, que contém o token de ID e o endereço de e-mail.
  3. O desenvolvedor cria um objeto Account usando o endereço de e-mail.
  4. O desenvolvedor chama a API Authorization com o escopo GAMES_LITE e a conta.
  5. Se a conta tiver uma concessão pré-existente no escopo GAMES_LITE, a API Authorization vai retornar um token diretamente no objeto de resposta.
    1. Use o token de resposta para chamar os servidores dos serviços do Google Play Games e recuperar os Player ID.
    2. O desenvolvedor verifica se os serviços do Google Play Games Player ID foram vinculados a uma conta no jogo.
      1. O desenvolvedor sabe que esse é um usuário recorrente dos serviços do Google Play Games v1.
    3. O desenvolvedor pode vincular o novo ID do GAIA à conta anterior dos serviços do Google Play Games v1.
  6. Ou, se a conta não tiver uma concessão pré-existente no escopo GAMES_LITE, a API Authorization vai retornar um PendingIntent.
    1. O desenvolvedor sabe que o usuário não tem uma conta dos serviços do Google Play Games v1.
    2. O desenvolvedor pode descartar com segurança o PendingIntent sem mostrar nenhuma interface.

Opção 2: para jogos que já vinculam o IGA ao OpenID

Os desenvolvedores desse grupo têm o caminho de migração mais simples. Se a conta no jogo já estiver vinculada principalmente ao OpenID, basta realizar a migração técnica padrão do SDK da v1 para a v2, conforme descrito nas etapas.

Atualizar o código de login automático

Substitua a classe de inicialização PlayGamesClientConfiguration pela classe PlayGamesPlatform.Instance.Authenticate(). A inicialização e a ativação do PlayGamesPlatform não são necessárias. Chamar PlayGamesPlatform.Instance.Authenticate() busca o resultado do login automático. Para mais informações sobre o fluxo de autenticação recomendado com a integração dos serviços do Google Play Games v2, consulte Diretriz de experiência do usuário para o fluxo de autenticação ideal.

C#

No editor do Unity, localize os arquivos com a 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();
}

E atualize para o seguinte:

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

Escolher uma plataforma social

Para escolher uma plataforma social, consulte escolher uma plataforma social.

Extrair códigos de autenticação do servidor

Para receber códigos de acesso do lado do servidor, consulte extrair códigos de autenticação do servidor.

Remover código de saída

Remova o código para sair. Os serviços do Google Play Games não exigem mais um botão de saída no jogo.

Remova o código mostrado no exemplo a seguir:

C#

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

Testar o jogo

Teste o jogo para garantir que ele funcione como planejado. Os testes que você realiza dependem dos recursos do jogo.

Confira a seguir uma lista de testes comuns para executar.

  1. Login concluído.

    1. O login automático funciona. O usuário precisa fazer login nos serviços do Google Play Games ao iniciar o jogo.

    2. O pop-up de boas-vindas é exibido.

      Exemplo de pop-up de boas-vindas.
      Exemplo de pop-up de boas-vindas (clique para ampliar).

    3. As mensagens de registro bem-sucedidas são exibidas. Execute o seguinte comando no terminal:

      adb logcat | grep com.google.android.

      Confira um exemplo de mensagem de registro bem-sucedida:

      [$PlaylogGamesSignInAction$SignInPerformerSource@e1cdecc
      number=1 name=GAMES_SERVICE_BROKER>], returning true for shouldShowWelcomePopup.
      [CONTEXT service_id=1 ]
  2. Garanta a consistência dos componentes da interface.

    1. Os pop-ups, placares e conquistas são exibidos corretamente e de forma consistente em vários tamanhos e orientações de tela na interface do usuário (UI) dos Serviços do Google Play Games.

    2. A opção de sair não está visível na interface dos serviços do Google Play Games.

    3. Verifique se é possível recuperar o ID do jogador e, se aplicável, se os recursos do lado do servidor funcionam conforme o esperado.

    4. Se o jogo usar autenticação do lado do servidor, teste completamente o fluxo requestServerSideAccess. Verifique se o servidor recebe o código de autenticação e pode trocá-lo por um token de acesso. Teste cenários de sucesso e falha para erros de rede e cenários de client ID inválidos.

Se o jogo usava algum dos seguintes recursos, teste-os para garantir que funcionem da mesma forma que antes da migração:

  • Placares: envie pontuações e confira os placares. Verifique se o ranking e a exibição dos nomes e pontuações dos jogadores estão corretos.
  • Conquistas: desbloqueie conquistas e verifique se elas estão sendo registradas e exibidas corretamente na interface do Play Games.
  • Jogos salvos: se o jogo usar jogos salvos, verifique se o salvamento e o carregamento do progresso do jogo funcionam perfeitamente. Isso é especialmente importante para testar em vários dispositivos e após atualizações do app.

Tarefas pós-migração

Conclua as etapas a seguir depois de migrar para o SDK do Games v2.

  1. Usar a Assinatura de apps do Google Play

  2. Criar um arquivo AAB

  3. Criar uma versão de teste interno

  4. Verificar suas credenciais de assinatura de app