Play Oyun Hizmetleri v2'ye (Unity) taşıma

Bu belgede, mevcut oyunların games v1 SDK'sından games v2 SDK'sına nasıl taşınacağı açıklanmaktadır. Unity için Play Games eklentisinin 10 ve önceki sürümlerinde games v1 SDK'sı kullanılır.

Başlamadan önce

  • Play Console'u ayarladığınızdan ve Unity Editor'ü yüklediğinizden emin olun.

Unity için Google Play Games eklentisini indirin

Play Games Hizmetleri'ndeki en yeni özelliklerden yararlanmak için en yeni eklenti sürümünü indirip yükleyin. GitHub deposundan indirin.

Eski eklentiyi kaldırın

Unity Editor'da aşağıdaki klasörleri veya dosyaları kaldırın.

Assets/GooglePlayGames

Assets/GeneratedLocalRepo/GooglePlayGames

Assets/Plugins/Android/GooglePlayGamesManifest.androidlib

Assets/Plugins/Android
Unity projenizde vurgulanan klasörleri kaldırın.
Unity projenizdeki vurgulanmış klasörleri kaldırın (büyütmek için tıklayın).

Yeni eklentiyi Unity projenize aktarın.

Eklentiyi Unity projenize aktarmak için aşağıdaki adımları uygulayın:

  1. Oyun projenizi açın.
  2. İndirilen Assets > Import Package > Custom Package'ı (Öğeler > Paket İçe Aktar > Özel Paket) tıklayarak unitypackage dosyasını projenizin öğelerine aktarın.
  3. Mevcut derleme platformunuzun Android olarak ayarlandığından emin olun.

    1. Ana menüde File > Build Settings'i (Dosya > Derleme Ayarları) tıklayın.

    2. Android'i seçin ve Switch Platform'u (Platformu Değiştir) tıklayın.

    3. Window > Google Play Games altında yeni bir menü öğesi olmalıdır. Yoksa Assets > Refresh'i (Öğeler > Yenile) tıklayarak öğeleri yenileyin ve ardından derleme platformunu tekrar ayarlamayı deneyin.

  4. Unity Düzenleyicisi'nde File > Build Settings > Player Settings > Other Settings'i (Dosya > Derleme Ayarları > Oyuncu Ayarları > Diğer Ayarlar) tıklayın.

  5. Target API level (Hedef API düzeyi) kutusunda bir sürüm seçin.

  6. Scripting backend (Komut dosyası oluşturma arka ucu) kutusuna IL2CPP girin.

  7. Target architectures (Hedef mimariler) kutusunda bir değer seçin.

  8. Paket adını not edin (package_name). Bu bilgileri daha sonra kullanabilirsiniz.

    Unity projenizdeki oynatıcı ayarları
    Unity projenizdeki oynatıcı ayarları.
  9. Android kaynaklarını Play Console'dan kopyalama

  10. Android kaynaklarını Unity projenize ekleme

Taşıma yolları

Oyununuz için doğru taşıma yolu, Play Games Hizmetleri v1'i nasıl uyguladığına ve oyuncu kimliğini nasıl işlediğine bağlıdır. Sorunsuz bir geçiş sağlamak ve oyuncu verilerinin kaybolmasını önlemek için mevcut kurulumunuza en uygun senaryoyu belirleyin ve ilgili adımları uygulayın.

1. seçenek: IGA'nın Play Oyun Hizmetleri oyuncu kimliğine bağlı olduğu oyunlar için

Bu senaryo, oyuncunun oyun içi hesabının (IGA) tek tanımlayıcısı olarak Play Games Hizmetleri'ni Player ID kullanan ve daha önce OpenID istememiş veya depolamamış oyunlar için geçerlidir. Buradaki temel zorluk, mevcut IGA'yı birincil tanımlayıcıya (OpenID) bağlarken oyuncunun ilerlemesiyle olan bağlantıyı kaybetmemektir.

Taşıma akışı aşağıdaki adımları içerir:

  1. Oyun başlatıldığında Play Games Hizmetleri v2 SDK'sı, platformun kimliğini otomatik olarak ve sessizce doğrular.
  2. Oyun, giriş ekranını gösterir. Bu ekranda, Google Play düğmesinin yerini alan bir Google ile oturum açma (SiWG) düğmesi bulunmalıdır. Entegre etmek için:

    1. CredManBridge.java dosyasını klasörünüze indirin. Bu Java sınıfı, Unity ile androidx.credentials kitaplığı arasında köprü görevi görür.

      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,<0x0x0A> interactiveRequest,<0x0x0A> cancellationSignal,<0x0x0A> executor,<0x0x0A> 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. Kimlik Bilgisi Yöneticisi Entegrasyonu:

      • Yalnızca uygulamayı daha önce yetkilendirmiş kullanıcıların oturum açmasını sağlamak için sessiz oturum açma işlemlerinde GetGoogleIdOption ile setFilterByAuthorizedAccounts(true)'ı kullanın.
      • Kullanıcıların bir hesap seçmesine veya yeni bir hesap eklemesine izin vermek için etkileşimli oturum açma işlemlerinde setFilterByAuthorizedAccounts(false) simgesini kullanın.
    3. Kapsam İsteği:

      • Temel Google kimlik bilgisini aldıktan sonra, belirli eski kapsamı isteyen bir AuthorizationRequest oluşturur: https://www.googleapis.com/auth/games_lite.
      • Bu kapsam, sunucuya kullanıcının eski PlayerID'sini arama izni verdiği için kritik önem taşır.
    4. Sonuç İşleme:

      • Kullanıcı izin verirse (veya daha önce izin vermişse) köprü, ServerAuthCode değerini Unity'ye döndürür.
      • Kullanıcı izin vermediyse (Yeni Kullanıcı senaryosu) API, PendingIntent döndürür. Bu örnekte, akışı basitleştirmek için amaç atılır ve kullanıcı yeni kullanıcı olarak değerlendirilir.
  3. Kimlik Bilgisi Yöneticisi ve Google Kimlik Hizmetleri'ni desteklemek için aşağıdaki bağımlılıkların mainTemplate.gradle gradle yapılandırmanıza eklendiğinden emin olun.

    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'
    }
    • Kimlik bilgisi yöneticisi: Hesap seçimi için temel kimlik düzenlemesini ve kullanıcı arayüzünü yönetir.
    • GoogleID Library: Özellikle GetGoogleIdOption için OpenID Connect jetonlarını alma olanağı sağlar.
    • Play Hizmetleri Auth: Uyumluluğu korumak ve eski Player ID alma işlemi için GAMES_LITE kapsamını istemek üzere gereklidir.
  4. Oyuncu SiWG düğmesine dokunup bir Google Hesabı seçtiğinde oyunun iki farklı tanımlayıcıyı alması gerekir:

    • IGA'yı bağlamak için kullanılan birincil tanımlayıcı olan OpenID.
    • Oyuncunun arka uç sisteminizdeki IGA'sını aramak ve bağlamayı gerçekleştirmek için GAMES_LITE kapsamı kullanılarak alınan Play Games Hizmetleri Player ID.
  5. Sonraki oyun lansmanlarında oyuncular, oyunların birincil tanımlayıcı olarak Player ID kullanmasını gerektirmeden SiWG akışıyla IGA'larına erişebilir.

4. adımı bir oyun istemci tarafı uygulaması kullanarak gerçekleştirebilirsiniz.

  1. Geliştirici, kullanıcının Google Hesabı ile oturum açması için Android Kimlik Bilgisi Yöneticisi API'sini çağırır.
  2. Kullanıcı SiwG'yi tamamlayıp bir Google Hesabı seçtikten sonra geliştirici, kimlik jetonunu ve e-posta adresini içeren bir sonuç nesnesi alır.
  3. Geliştirici, e-posta adresinden bir Hesap nesnesi oluşturur.
  4. Geliştirici, GAMES_LITE kapsamı ve hesapla birlikte Authorization API'yi çağırır.
  5. Hesapta GAMES_LITE kapsamı için önceden verilmiş bir izin varsa Authorization API, yanıt nesnesinde doğrudan bir jeton döndürür.
    1. Play Oyun Hizmetleri sunucularını çağırmak ve Play Oyun Hizmetleri Player ID'ni almak için yanıt jetonunu kullanın.
    2. Geliştirici, Play Games Hizmetleri Player ID öğesinin oyun içi bir hesaba bağlanıp bağlanmadığını doğrular.
      1. Geliştirici, bu kullanıcının Play Games Hizmetleri v1'den geri dönen bir kullanıcı olduğunu biliyor.
    3. Geliştirici, yeni gaia kimliğini önceki Play Games Hizmetleri v1 hesabına bağlayabilir.
  6. Alternatif olarak, hesapta GAMES_LITE kapsamında önceden verilmiş bir izin yoksa Authorization API bir PendingIntent döndürür.
    1. Geliştirici, kullanıcının Play Games Hizmetleri v1'den mevcut bir hesabı olmadığını biliyor.
    2. Geliştirici, herhangi bir kullanıcı arayüzü göstermeden PendingIntent'i güvenli bir şekilde silebilir.

2. seçenek: IGA'yı OpenID'ye zaten bağlayan oyunlar için

Bu gruptaki geliştiriciler, en basit geçiş yoluna sahiptir. Oyununuzun oyun içi hesabı zaten öncelikli olarak OpenID'ye bağlıysa yalnızca adımlarda belirtildiği gibi v1'den v2'ye standart teknik SDK taşıma işlemini gerçekleştirmeniz gerekir.

Otomatik oturum açma kodunu güncelleme

PlayGamesClientConfiguration başlatma sınıfını PlayGamesPlatform.Instance.Authenticate() sınıfıyla değiştirin. PlayGamesPlatform başlatılması ve etkinleştirilmesi gerekmez. Calling PlayGamesPlatform.Instance.Authenticate(), otomatik oturum açma sonucunu getirir. Play Oyun Hizmetleri v2 entegrasyonu ile önerilen kimlik doğrulama akışı hakkında daha fazla bilgi için İdeal kimlik doğrulama akışına yönelik kullanıcı deneyimi yönergeleri başlıklı makaleyi inceleyin.

C#

Unity Editor'da PlayGamesClientConfiguration sınıfına sahip dosyaları bulun.

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

Şu şekilde güncelleyin:

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

Sosyal medya platformu seçme

Sosyal medya platformu seçmek için sosyal medya platformu seçme başlıklı makaleyi inceleyin.

Sunucu kimlik doğrulama kodlarını alma

Sunucu tarafı erişim kodlarını almak için sunucu kimlik doğrulama kodlarını alma başlıklı makaleyi inceleyin.

Oturumu kapatma kodunu kaldırma

Oturumu kapatma kodunu kaldırın. Play Games Hizmetleri artık oyun içi oturum kapatma düğmesi gerektirmiyor.

Aşağıdaki örnekte gösterilen kodu kaldırın:

C#

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

Oyununuzu test etme

Oyununuzu test ederek tasarlandığı şekilde çalıştığından emin olun. Yaptığınız testler oyununuzun özelliklerine bağlıdır.

Aşağıda, çalıştırılacak yaygın testlerin listesi verilmiştir.

  1. Başarılı oturum açma.

    1. Otomatik oturum açma çalışır. Kullanıcı, oyunu başlattığında Play Oyun Hizmetleri'nde oturum açmış olmalıdır.

    2. Karşılama pop-up'ı gösterilir.

      Örnek karşılama pop-up&#39;ı.
      Örnek karşılama pop-up'ı (büyütmek için tıklayın).

    3. Başarılı günlük mesajları gösterilir. Terminalde aşağıdaki komutu çalıştırın:

      adb logcat | grep com.google.android.

      Başarılı bir günlük mesajı aşağıdaki örnekte gösterilmektedir:

      [$PlaylogGamesSignInAction$SignInPerformerSource@e1cdecc
      number=1 name=GAMES_SERVICE_BROKER>], returning true for shouldShowWelcomePopup.
      [CONTEXT service_id=1 ]
  2. Kullanıcı arayüzü bileşenlerinin tutarlı olmasını sağlama.

    1. Pop-up'lar, skor tabloları ve başarılar, Play Oyun Hizmetleri kullanıcı arayüzünde (UI) çeşitli ekran boyutları ve yönlerinde doğru ve tutarlı bir şekilde gösteriliyor.

    2. Oturumu kapatma seçeneği, Play Oyun Hizmetleri kullanıcı arayüzünde görünmüyor.

    3. Oyuncu kimliğini başarıyla alabileceğinizden ve varsa sunucu tarafı özelliklerinin beklendiği gibi çalıştığından emin olun.

    4. Oyun sunucu tarafı kimlik doğrulamayı kullanıyorsa requestServerSideAccess akışını kapsamlı bir şekilde test edin. Sunucunun yetkilendirme kodunu aldığından ve erişim jetonuyla değiştirebildiğinden emin olun. Ağ hataları ve geçersiz senaryolar için hem başarılı hem de başarısız senaryoları test edin.client ID

Oyununuzda aşağıdaki özelliklerden herhangi biri kullanılıyorsa bunların taşıma işleminden önceki gibi çalıştığından emin olmak için test edin:

  • Skor tabloları: Skor gönderin ve skor tablolarını görüntüleyin. Oyuncu adlarının ve skorların doğru sıralandığını ve gösterildiğini kontrol edin.
  • Başarılar: Başarıların kilidini açın ve Play Games kullanıcı arayüzünde doğru şekilde kaydedilip gösterildiğini doğrulayın.
  • Kaydedilmiş Oyunlar: Oyun kaydedilmiş oyunları kullanıyorsa oyun ilerleme durumunun kaydedilmesi ve yüklenmesinin sorunsuz çalıştığından emin olun. Bu durum, özellikle birden fazla cihazda ve uygulama güncellemelerinden sonra test etmek için önemlidir.

Taşıma sonrası görevler

Games v2 SDK'ya geçiş yaptıktan sonra aşağıdaki adımları tamamlayın.

  1. Play Uygulama İmzalama'yı kullanma

  2. AAB dosyası oluşturma

  3. Dahili test sürümü oluşturma

  4. Uygulama imzalama kimlik bilgilerinizi doğrulama