این سند نحوه انتقال بازیهای موجود از games v1 SDK به games v2 SDK را شرح میدهد. افزونه Play Games برای Unity، نسخههای 10 و قبل از آن، از games v1 SDK استفاده میکند.
قبل از اینکه شروع کنی
- مطمئن شوید که قبلاً Play Console را راهاندازی کرده و Unity Editor را نصب کردهاید.
افزونه Google Play Games را برای Unity دانلود کنید
برای بهرهمندی از جدیدترین ویژگیهای سرویسهای بازیهای Play، آخرین نسخه افزونه را دانلود و نصب کنید. آن را از مخزن gitHub دانلود کنید.
افزونه قدیمی را حذف کنید
در ویرایشگر Unity، پوشهها یا فایلهای زیر را حذف کنید.
Assets/GooglePlayGames Assets/GeneratedLocalRepo/GooglePlayGames Assets/Plugins/Android/GooglePlayGamesManifest.androidlib Assets/Plugins/Android

افزونه جدید را به پروژه Unity خود وارد کنید
برای وارد کردن افزونه به پروژه Unity خود، این مراحل را دنبال کنید:
- پروژه بازی خود را باز کنید.
- در ویرایشگر یونیتی، روی Assets > Import Package > Custom Package کلیک کنید تا فایل
unitypackageدانلود شده را به asset های پروژه خود وارد کنید. مطمئن شوید که پلتفرم ساخت فعلی شما روی اندروید تنظیم شده است.
در منوی اصلی، روی File > Build Settings کلیک کنید.
اندروید را انتخاب کنید و روی «تغییر پلتفرم» کلیک کنید.
باید یک آیتم منوی جدید در زیر Window > Google Play Games وجود داشته باشد. اگر وجود ندارد، با کلیک روی Assets > Refresh ، فایلها را بهروزرسانی کنید و سپس دوباره سعی کنید پلتفرم ساخت را تنظیم کنید.
در ویرایشگر یونیتی، روی فایل > تنظیمات ساخت > تنظیمات پخشکننده > سایر تنظیمات کلیک کنید.
در کادر Target API level ، یک نسخه را انتخاب کنید.
در کادر Scripting backend ،
IL2CPPرا وارد کنید.در کادر Target architectures ، یک مقدار انتخاب کنید.
به نام بسته package_name توجه کنید. میتوانید بعداً از این اطلاعات استفاده کنید.

تنظیمات پخشکننده در پروژه یونیتی شما.
مسیرهای مهاجرت
مسیر صحیح مهاجرت برای بازی شما به نحوه پیادهسازی Play Games Services v1 و مدیریت هویت بازیکن بستگی دارد. برای اطمینان از انتقال روان و جلوگیری از از دست رفتن اطلاعات بازیکن، سناریویی را که به بهترین وجه با تنظیمات موجود شما مطابقت دارد، شناسایی کرده و مراحل مربوطه را دنبال کنید.
گزینه ۱: برای بازیهایی که IGA ملزم به استفاده از شناسه بازیکن سرویسهای Play Games است
این سناریو در مورد بازیهایی اعمال میشود که Player ID Play Games Services به عنوان تنها شناسه برای حساب درون بازی (IGA) بازیکن استفاده کردهاند و قبلاً OpenID درخواست یا ذخیره نکردهاند. چالش اصلی، پیوند دادن IGA موجود به یک شناسه اصلی ( OpenID ) بدون از دست دادن ارتباط با پیشرفت بازیکن است.
جریان مهاجرت شامل مراحل زیر است:
- وقتی بازی اجرا میشود، Play Games Services v2 SDK به طور خودکار و بیصدا پلتفرم را احراز هویت میکند.
بازی صفحه ورود به سیستم خود را نمایش میدهد. این صفحه باید دارای دکمه ورود با گوگل (SiWG) باشد که جایگزین دکمه گوگل پلی میشود. برای ادغام:
فایل CredManBridge.java را در پوشه خود دانلود کنید. این کلاس جاوا به عنوان پلی بین Unity و کتابخانه
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"); } }); }
// --- حالت ۲: ورود تعاملی (با کلیک روی دکمه فراخوانی میشود) --- // صفحه انتخاب حساب / "افزودن حساب" را مجبور به نمایش میکند. public static void signInInteractive(Context context, String webClientId) { CredentialManager credentialManager = CredentialManager.create(context); CancellationSignal cancellationSignal = new CancellationSignal(); Executor executor = Executors.newSingleThreadExecutor();
Log.d("CredMan", "شروع ورود تعاملی...");
GetGoogleIdOption interactiveOption = new GetGoogleIdOption.Builder() .setFilterByAuthorizedAccounts(false) // نمایش همه حسابها (و "افزودن حساب") .setServerClientId(webClientId) .setAutoSelectEnabled(false) // نمایش اجباری رابط کاربری .build();
GetCredentialRequest interactiveRequest = new GetCredentialRequest.Builder().addCredentialOption(interactiveOption).build();
credentialManager.getCredentialAsync(context, interactiveRequest, cancellationSignal, executor, new androidx.credentials.CredentialManagerCallback
() { @Override public void onResult(GetCredentialResponse result) { Log.d("CredMan", "ورود تعاملی موفقیتآمیز بود!"); handleSignInResult(context, result, webClientId); } @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", "خطای تجزیه: " + e.getMessage()); } } }
یکپارچهسازی مدیریت اعتبارنامهها:
- برای ورود بیصدا،
GetGoogleIdOptionبه همراهsetFilterByAuthorizedAccounts(true)استفاده کنید تا فقط کاربرانی که قبلاً برنامه را تأیید کردهاند، وارد سیستم شوند. - برای ورودهای تعاملی
setFilterByAuthorizedAccounts(false)استفاده کنید تا به کاربران اجازه دهید یک حساب کاربری انتخاب کنند یا یک حساب کاربری جدید اضافه کنند.
- برای ورود بیصدا،
درخواست محدوده:
- پس از دریافت اعتبارنامه پایه گوگل، یک
AuthorizationRequestایجاد میکند که محدوده خاص legacy scope را درخواست میکند: https://www.googleapis.com/auth/games_lite . - این محدوده بسیار مهم است زیرا به سرور اجازه میدهد تا PlayerID قدیمی کاربر را جستجو کند.
- پس از دریافت اعتبارنامه پایه گوگل، یک
پردازش نتایج:
- اگر کاربر اجازه دهد (یا قبلاً آن را داده باشد)، پل،
ServerAuthCodeرا به Unity برمیگرداند. - اگر کاربر مجوزی اعطا نکرده باشد (سناریوی کاربر جدید)، API یک
PendingIntentبرمیگرداند. در این نمونه، اینتنت نادیده گرفته میشود و کاربر به عنوان یک کاربر جدید در نظر گرفته میشود تا روند کار سادهتر شود.
- اگر کاربر اجازه دهد (یا قبلاً آن را داده باشد)، پل،
برای پشتیبانی از سرویسهای Credential Manager و Google Identity، مطمئن شوید که وابستگیهای زیر به پیکربندی 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' }
- مدیر اعتبارنامه: هماهنگسازی هویت اصلی و رابط کاربری برای انتخاب حساب را مدیریت میکند.
- کتابخانه GoogleID: به طور خاص
GetGoogleIdOptionبرای بازیابی توکنهایOpenIDConnect ارائه میدهد. - تأیید سرویسهای پخش: برای حفظ سازگاری و درخواست دامنه
GAMES_LITEبرای بازیابیPlayer IDقدیمی، مورد نیاز است.
وقتی بازیکن دکمه SiWG را لمس میکند و یک حساب گوگل انتخاب میکند، بازی باید دو شناسه مجزا را بازیابی کند:
-
OpenID، شناسه اصلی برای اتصال IGA. -
Player IDسرویسهای بازیهای Play، که با استفاده از دامنهGAMES_LITEبازیابی میشود، برای جستجوی IGA بازیکن در سیستم backend شما و انجام اتصال.
-
در انتشارهای بعدی بازی، بازیکنان میتوانند از طریق جریان SiWG به IGA خود دسترسی پیدا کنند، بدون اینکه بازیها از
Player IDبه عنوان شناسه اصلی استفاده کنند.
شما میتوانید مرحله ۴ را با استفاده از پیادهسازی سمت کلاینت بازی انجام دهید.
- توسعهدهنده، API مدیریت اعتبارنامه اندروید را فراخوانی میکند تا کاربر را با یک حساب گوگل وارد سیستم کند.
- پس از اینکه کاربر SiwG را تکمیل و یک حساب گوگل انتخاب کرد، توسعهدهنده یک شیء نتیجه دریافت میکند که حاوی توکن شناسه و آدرس ایمیل است.
- توسعهدهنده یک شیء حساب کاربری (Account) از آدرس ایمیل میسازد.
- توسعهدهنده، API احراز هویت را با دامنه
GAMES_LITEو حساب کاربری فراخوانی میکند. - اگر حساب کاربری از قبل در محدوده
GAMES_LITEمجوز داشته باشد، API احراز هویت یک توکن را مستقیماً در شیء پاسخ برمیگرداند.- از توکن پاسخ برای فراخوانی سرورهای Play Games Services و بازیابی
Player IDPlay Games Services استفاده کنید. - توسعهدهنده تأیید میکند که آیا
Player IDPlay Games Services به یک حساب درونبازی مرتبط شده است یا خیر.- توسعهدهنده میداند که این یک کاربر قدیمی از Play Games Services نسخه ۱ است.
- توسعهدهنده میتواند شناسه جدید گایا را به حساب قبلی Play Games Services v1 پیوند دهد.
- از توکن پاسخ برای فراخوانی سرورهای Play Games Services و بازیابی
- یا اگر حساب کاربری از قبل مجوزی در محدوده
GAMES_LITEنداشته باشد، API احراز هویت یک PendingIntent برمیگرداند.- توسعهدهنده میداند که کاربر از Play Games Services نسخه ۱ حساب کاربری ندارد.
- توسعهدهنده میتواند با خیال راحت PendingIntent را بدون نمایش هیچ رابط کاربری (UI) حذف کند.
گزینه ۲: برای بازیهایی که از قبل IGA را به OpenID متصل کردهاند
توسعهدهندگان این گروه، سادهترین مسیر مهاجرت را دارند. اگر حساب درون بازی شما از قبل به OpenID متصل است، فقط باید مهاجرت استاندارد فنی SDK را از نسخه ۱ به نسخه ۲، همانطور که در مراحل ذکر شده است، انجام دهید.
کد ورود خودکار را بهروزرسانی کنید
کلاس مقداردهی اولیه PlayGamesClientConfiguration را با کلاس PlayGamesPlatform.Instance.Authenticate() جایگزین کنید. مقداردهی اولیه و فعالسازی PlayGamesPlatform الزامی نیست. فراخوانی PlayGamesPlatform.Instance.Authenticate() نتیجه ورود خودکار را دریافت میکند. برای اطلاعات بیشتر در مورد جریان احراز هویت توصیهشده با ادغام Play Games Services v2، به راهنمای تجربه کاربری برای جریان احراز هویت ایدهآل مراجعه کنید.
سی شارپ
در ویرایشگر یونیتی، فایلهای حاوی کلاس 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();
}
و آن را به این بهروزرسانی کنید:
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).
}
}
یک پلتفرم اجتماعی انتخاب کنید
برای انتخاب یک پلتفرم اجتماعی، به «انتخاب یک پلتفرم اجتماعی» مراجعه کنید.
کدهای احراز هویت سرور را بازیابی کنید
برای دریافت کدهای دسترسی سمت سرور، به بازیابی کدهای احراز هویت سرور مراجعه کنید.
حذف کد خروج
کد خروج از سیستم را حذف کنید. سرویسهای بازیهای Play دیگر نیازی به دکمه خروج از بازی ندارند.
کد نشان داده شده در مثال زیر را حذف کنید:
سی شارپ
// sign out
PlayGamesPlatform.Instance.SignOut();
بازی خود را آزمایش کنید
با آزمایش کردن بازی خود، از عملکرد آن مطابق با طراحی اطمینان حاصل کنید. آزمایشهایی که انجام میدهید به ویژگیهای بازی شما بستگی دارد.
در ادامه لیستی از آزمایشهای رایج برای اجرا آمده است.
ورود موفقیتآمیز .
ورود خودکار کار میکند. کاربر باید هنگام اجرای بازی، وارد سرویسهای بازیهای پلی شود.
پنجره خوشامدگویی نمایش داده میشود.
پیامهای ثبت موفقیتآمیز نمایش داده میشوند. دستور زیر را در ترمینال اجرا کنید:
adb logcat | grep com.google.android.
یک پیام ثبت موفقیتآمیز در مثال زیر نشان داده شده است:
[
$PlaylogGamesSignInAction$SignInPerformerSource@e1cdecc number=1 name=GAMES_SERVICE_BROKER>], returning true for shouldShowWelcomePopup. [CONTEXT service_id=1 ]
از سازگاری اجزای رابط کاربری اطمینان حاصل کنید .
پنجرههای بازشو، جدول امتیازات و دستاوردها به درستی و به طور مداوم در اندازهها و جهتهای مختلف صفحه نمایش در رابط کاربری (UI) سرویسهای بازیهای Play نمایش داده میشوند.
گزینه خروج از سیستم در رابط کاربری سرویسهای بازیهای پلی قابل مشاهده نیست.
مطمئن شوید که میتوانید با موفقیت شناسه بازیکن را بازیابی کنید، و در صورت لزوم، قابلیتهای سمت سرور مطابق انتظار کار میکنند.
اگر بازی از احراز هویت سمت سرور استفاده میکند، جریان
requestServerSideAccessرا به طور کامل آزمایش کنید. مطمئن شوید که سرور کد احراز هویت را دریافت میکند و میتواند آن را با یک توکن دسترسی مبادله کند. سناریوهای موفقیت و شکست را برای خطاهای شبکه و سناریوهایclient IDنامعتبر آزمایش کنید.
اگر بازی شما از هر یک از ویژگیهای زیر استفاده میکرد، آنها را آزمایش کنید تا مطمئن شوید که مانند قبل از انتقال کار میکنند:
- جدول امتیازات : امتیازات را ارسال کنید و جدول امتیازات را مشاهده کنید. رتبهبندی صحیح و نمایش نام و امتیازات بازیکنان را بررسی کنید.
- دستاوردها : دستاوردها را باز کنید و تأیید کنید که آنها به درستی ثبت شده و در رابط کاربری بازیهای Play نمایش داده میشوند.
- بازیهای ذخیرهشده : اگر بازی از بازیهای ذخیرهشده استفاده میکند، مطمئن شوید که ذخیره و بارگذاری پیشرفت بازی بینقص انجام میشود. این امر بهویژه برای آزمایش در چندین دستگاه و پس از بهروزرسانیهای برنامه بسیار مهم است.
وظایف پس از مهاجرت
پس از مهاجرت به SDK بازیها نسخه ۲، مراحل زیر را انجام دهید.
