Bermigrasi ke Layanan game Play v2 (Unity)

Dokumen ini menjelaskan cara memigrasikan game yang ada dari SDK game v1 ke SDK game v2. Plugin Play Game untuk Unity, versi 10 dan yang lebih lama, menggunakan SDK game v1.

Sebelum memulai

  • Pastikan Anda telah menyiapkan Konsol Play dan menginstal Editor Unity.

Download plugin Google Play Game untuk Unity

Untuk memanfaatkan fitur terbaru di Layanan Play Games, download dan instal versi plugin terbaru. Download dari repositori GitHub.

Menghapus plugin lama

Di Editor Unity, hapus folder atau file berikut.

Assets/GooglePlayGames

Assets/GeneratedLocalRepo/GooglePlayGames

Assets/Plugins/Android/GooglePlayGamesManifest.androidlib

Assets/Plugins/Android
Hapus folder yang ditandai di project Unity Anda.
Hapus folder yang ditandai di project Unity Anda (klik untuk memperbesar).

Mengimpor plugin baru ke project Unity Anda

Untuk mengimpor plugin ke project Unity Anda, ikuti langkah-langkah berikut:

  1. Buka project game Anda.
  2. Di Editor Unity, klik Assets > Import Package > Custom Package untuk mengimpor file unitypackage yang didownload ke aset project Anda.
  3. Pastikan platform build Anda saat ini disetel ke Android.

    1. Di menu utama, klik File > Build Settings.

    2. Pilih Android lalu klik Switch Platform.

    3. Harus ada item menu baru di bagian Window > Google Play Game. Jika tidak ada, muat ulang aset dengan mengklik Assets > Refresh , lalu coba tetapkan platform build lagi.

  4. Di Editor Unity, klik File > Build Settings > Player Settings > Other Settings.

  5. Di kotak level API target, pilih versi.

  6. Di kotak Scripting backend, masukkan IL2CPP.

  7. Di kotak Target architectures, pilih nilai.

  8. Perhatikan nama paket package_name.Anda dapat menggunakan informasi ini nanti.

    Setelan pemain di project Unity Anda
    Setelan pemain di project Unity Anda.
  9. Salin resource Android dari Konsol Play

  10. Tambahkan resource Android ke project Unity Anda

Jalur migrasi

Jalur migrasi yang benar untuk game Anda bergantung pada cara game tersebut menerapkan Layanan Play Games v1 dan menangani identitas pemain. Untuk memastikan transisi yang lancar dan mencegah kehilangan data pemain, identifikasi skenario yang paling sesuai dengan penyiapan yang ada dan ikuti langkah-langkah yang sesuai.

Opsi 1: Untuk Game tempat IGA terikat ke ID Pemain Layanan Play Games

Skenario ini berlaku untuk game yang telah menggunakan Layanan Play Games Player ID sebagai satu-satunya ID untuk Akun Dalam Game (IGA) pemain dan belum pernah meminta atau menyimpan OpenID. Tantangan utamanya adalah menautkan IGA yang ada ke ID utama (OpenID) tanpa kehilangan koneksi ke progres pemain.

Alur migrasi mencakup langkah-langkah berikut:

  1. Saat game diluncurkan, SDK Layanan Play Games v2 akan otomatis dan diam-diam mengautentikasi platform.
  2. Game menampilkan layar login. Layar ini harus menampilkan tombol Sign in with Google (SiWG) , yang menggantikan tombol Google Play. Untuk mengintegrasikan:

    1. Download CredManBridge.java ke folder Anda. Class Java ini bertindak sebagai jembatan antara Unity dan library 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. Integrasi Pengelola Kredensial:

      • Gunakan GetGoogleIdOption dengan setFilterByAuthorizedAccounts(true) untuk login otomatis hanya untuk login pengguna yang sebelumnya telah mengotorisasi aplikasi.
      • Gunakan setFilterByAuthorizedAccounts(false) untuk login interaktif agar pengguna dapat memilih akun atau menambahkan akun baru.
    3. Permintaan Cakupan:

      • Setelah mendapatkan kredensial Google dasar, kredensial tersebut akan membuat AuthorizationRequest yang meminta cakupan lama tertentu: https://www.googleapis.com/auth/games_lite.
      • Cakupan ini sangat penting karena memberikan izin server untuk mencari PlayerID lama pengguna.
    4. Penanganan Hasil:

      • Jika pengguna memberikan izin (atau telah memberikannya sebelumnya), jembatan akan menampilkan ServerAuthCode ke Unity.
      • Jika pengguna belum memberikan izin (skenario Pengguna Baru), API akan menampilkan PendingIntent. Dalam contoh ini, intent akan dihapus, dan pengguna akan diperlakukan sebagai pengguna baru untuk menyederhanakan alur.
  3. Untuk mendukung layanan Pengelola Kredensial dan Identitas Google, pastikan dependensi berikut ditambahkan ke konfigurasi gradle mainTemplate.gradle Anda.

    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'
    }
    • Pengelola Kredensial: Menangani orkestrasi identitas inti dan UI untuk pemilihan akun.
    • Library GoogleID: Secara khusus menyediakan GetGoogleIdOption untuk mengambil token Connect OpenID.
    • Autentikasi Layanan Play: Diperlukan untuk mempertahankan kompatibilitas dan meminta cakupan GAMES_LITE untuk pengambilan Player ID lama.
  4. Saat pemain mengetuk tombol SiWG dan memilih Akun Google, game harus mengambil dua ID yang berbeda:

    • OpenID, ID utama untuk mengikat IGA.
    • Player ID Layanan Play Games, yang diambil menggunakan cakupan GAMES_LITE, untuk mencari IGA pemain di sistem backend Anda dan melakukan pengikatan.
  5. Pada peluncuran game berikutnya, pemain dapat mengakses IGA mereka melalui alur SiWG, tanpa mengharuskan game menggunakan Player ID sebagai ID utama.

Anda dapat melakukan langkah 4 menggunakan penerapan sisi klien game.

  1. Developer memanggil Android Credential Manager API untuk membuat pengguna login dengan Akun Google.
  2. Setelah pengguna menyelesaikan SiwG dan memilih Akun Google, developer akan menerima objek hasil, yang berisi token ID, alamat email.
  3. Developer membuat objek Akun dari alamat email.
  4. Developer memanggil Authorization API dengan cakupan GAMES_LITE dan Akun.
  5. Jika akun memiliki pemberian izin yang sudah ada sebelumnya pada cakupan GAMES_LITE, Authorization API akan menampilkan token langsung dalam objek respons.
    1. Gunakan token respons untuk memanggil server Layanan Play Games dan mengambil Player ID Layanan Play Games.
    2. Developer memverifikasi apakah Player ID Layanan Play Games ditautkan dengan akun dalam game.
      1. Developer mengetahui bahwa ini adalah pengguna yang kembali dari Layanan Play Games v1.
    3. Developer dapat menautkan ID gaia baru dengan akun Layanan Play Games v1 sebelumnya.
  6. Atau, jika akun tidak memiliki pemberian izin yang sudah ada sebelumnya pada cakupan GAMES_LITE, Authorization API akan menampilkan PendingIntent.
    1. Developer mengetahui bahwa pengguna tidak memiliki akun yang ada dari Layanan Play Games v1.
    2. Developer dapat menghapus PendingIntent dengan aman tanpa menampilkan UI apa pun.

Opsi 2: Untuk Game yang sudah mengikat IGA ke OpenID

Developer dalam grup ini memiliki jalur migrasi yang paling mudah. Jika akun dalam game Anda sudah terikat terutama ke OpenID, Anda hanya perlu melakukan migrasi SDK teknis standar dari v1 ke v2 seperti yang diuraikan dalam langkah-langkah.

Mengupdate kode login otomatis

Ganti class inisialisasi PlayGamesClientConfiguration dengan class PlayGamesPlatform.Instance.Authenticate(). Inisialisasi dan aktivasi PlayGamesPlatform tidak diperlukan. Memanggil PlayGamesPlatform.Instance.Authenticate() akan mengambil hasil login otomatis. Untuk mengetahui informasi selengkapnya tentang alur autentikasi yang direkomendasikan dengan integrasi Layanan Play Games v2, lihat Panduan pengalaman pengguna untuk alur autentikasi yang ideal.

C#

Di Editor Unity, temukan file dengan class 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();
}

Lalu, perbarui menjadi:

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

Memilih platform media sosial

Untuk memilih platform media sosial, lihat memilih platform media sosial.

Mengambil kode autentikasi server

Untuk mendapatkan kode akses sisi server, lihat mengambil kode autentikasi server.

Menghapus kode logout

Hapus kode untuk logout. Layanan Play Games tidak lagi memerlukan tombol logout dalam game.

Hapus kode yang ditampilkan dalam contoh berikut:

C#

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

Menguji game Anda

Pastikan game Anda berfungsi seperti yang dirancang dengan mengujinya. Pengujian yang Anda lakukan bergantung pada fitur game Anda.

Berikut adalah daftar pengujian umum yang akan dijalankan.

  1. Login berhasil.

    1. Login otomatis berfungsi. Pengguna harus login ke Layanan Play Games saat meluncurkan game.

    2. Pop-up sambutan ditampilkan.

      Contoh pop-up selamat datang.
      Contoh pop-up sambutan (klik untuk memperbesar).

    3. Pesan log yang berhasil ditampilkan. Jalankan perintah berikut di terminal:

      adb logcat | grep com.google.android.

      Pesan log yang berhasil ditampilkan dalam contoh berikut:

      [$PlaylogGamesSignInAction$SignInPerformerSource@e1cdecc
      number=1 name=GAMES_SERVICE_BROKER>], returning true for shouldShowWelcomePopup.
      [CONTEXT service_id=1 ]
  2. Memastikan konsistensi komponen UI.

    1. Pop-up, papan peringkat, dan pencapaian ditampilkan dengan benar dan konsisten pada berbagai ukuran dan orientasi layar di antarmuka pengguna (UI) Layanan Play Games.

    2. Opsi logout tidak terlihat di UI Layanan Play Games.

    3. Pastikan Anda dapat mengambil Player ID dengan berhasil, dan jika berlaku, kemampuan sisi server berfungsi seperti yang diharapkan.

    4. Jika game menggunakan autentikasi sisi server, uji alur requestServerSideAccess secara menyeluruh. Pastikan server menerima kode autentikasi dan dapat menukarnya dengan token akses. Uji skenario keberhasilan dan kegagalan untuk error jaringan, skenario client ID yang tidak valid.

Jika game Anda menggunakan salah satu fitur berikut, uji fitur tersebut untuk memastikan fitur tersebut berfungsi sama seperti sebelum migrasi:

  • Papan Peringkat: Kirim skor dan lihat papan peringkat. Periksa peringkat yang benar dan tampilan nama serta skor pemain.
  • Pencapaian: Buka pencapaian dan pastikan pencapaian tersebut dicatat dengan benar dan ditampilkan di UI Play Game.
  • Game Tersimpan: Jika game menggunakan game tersimpan, pastikan penyimpanan dan pemuatan progres game berfungsi dengan lancar. Hal ini sangat penting untuk diuji di beberapa perangkat dan setelah update aplikasi.

Tugas pascamigrasi

Selesaikan langkah-langkah berikut setelah Anda bermigrasi ke SDK game v2.

  1. Menggunakan Penandatanganan Aplikasi Play

  2. Membuat file AAB

  3. Membuat rilis pengujian internal

  4. Memverifikasi kredensial Penandatanganan aplikasi