تنظيم صفحاتك في مجموعات
يمكنك حفظ المحتوى وتصنيفه حسب إعداداتك المفضّلة.
يوضّح هذا الموضوع كيفية استخدام الألعاب المحفوظة في "خدمات ألعاب Play" في ألعاب Unity.
قبل البدء
إعداد مشروعك والمكوّن الإضافي "ألعاب Google Play" لمحرّك Unity للحصول على التفاصيل، يُرجى الاطّلاع على دليل البدء.
تم تفعيل خدمة "حفظ التقدم في الألعاب". اطّلِع على الألعاب المحفوظة للحصول على التفاصيل.
عرض واجهة مستخدم الألعاب المحفوظة
يتم عرض واجهة المستخدم العادية لاختيار أو إنشاء إدخال لعبة محفوظة من خلال استدعاء:
voidShowSelectUI(){uintmaxNumToDisplay=5;boolallowCreateNew=false;boolallowDelete=true;ISavedGameClientsavedGameClient=PlayGamesPlatform.Instance.SavedGame;savedGameClient.ShowSelectSavedGameUI("Select saved game",maxNumToDisplay,allowCreateNew,allowDelete,OnSavedGameSelected);}publicvoidOnSavedGameSelected(SelectUIStatusstatus,ISavedGameMetadatagame){if(status==SelectUIStatus.SavedGameSelected){// handle selected game save}else{// handle cancel or error}}
فتح لعبة محفوظة
لقراءة البيانات أو كتابتها في لعبة محفوظة، يجب فتح اللعبة المحفوظة. بما أنّ حالة اللعبة المحفوظة يتم تخزينها مؤقتًا على الجهاز وحفظها على السحابة الإلكترونية، من المحتمل حدوث تعارضات في حالة البيانات المحفوظة.
يحدث تعارض عندما يحاول جهاز حفظ الحالة على السحابة الإلكترونية، ولكن البيانات المتوفّرة حاليًا على السحابة الإلكترونية تمت كتابتها بواسطة جهاز آخر. ويجب حل هذه التعارضات عند فتح بيانات اللعبة المحفوظة.
هناك طريقتان مفتوحتان للتعامل مع حل التعارض، الأولى
OpenWithAutomaticConflictResolution تقبل استراتيجية حل قياسية
وتحل التعارضات تلقائيًا. تتلقّى الطريقة الأخرى،
OpenWithManualConflictResolution، طريقة ردّ الاتصال للسماح
بالحلّ اليدوي للتعارض.
يمكنك الاطّلاع على ISavedGameClient لمزيد من التفاصيل حول هذه الطرق.
voidOpenSavedGame(stringfilename){ISavedGameClientsavedGameClient=PlayGamesPlatform.Instance.SavedGame;savedGameClient.OpenWithAutomaticConflictResolution(filename,DataSource.ReadCacheOrNetwork,ConflictResolutionStrategy.UseLongestPlaytime,OnSavedGameOpened);}publicvoidOnSavedGameOpened(SavedGameRequestStatusstatus,ISavedGameMetadatagame){if(status==SavedGameRequestStatus.Success){// handle reading or writing of saved game.}else{// handle error}}
كتابة لعبة محفوظة
بعد فتح ملف اللعبة المحفوظة، يمكن الكتابة فيه لحفظ حالة اللعبة.
يتم ذلك من خلال استدعاء CommitUpdate. هناك أربع مَعلمات خاصة بـ CommitUpdate:
البيانات الوصفية للعبة المحفوظة التي تم تمريرها إلى دالة الرجوع التي تم تمريرها إلى إحدى دوال Open
التعديلات التي يجب إجراؤها على بيانات التعريف
مصفوفة البايت الفعلية للبيانات
دالة رد الاتصال التي سيتم استدعاؤها عند اكتمال عملية التنفيذ.
voidSaveGame(ISavedGameMetadatagame,byte[]savedData,TimeSpantotalPlaytime){ISavedGameClientsavedGameClient=PlayGamesPlatform.Instance.SavedGame;SavedGameMetadataUpdate.Builderbuilder=newSavedGameMetadataUpdate.Builder();builder=builder.WithUpdatedPlayedTime(totalPlaytime).WithUpdatedDescription("Saved game at "+DateTime.Now());if(savedImage!=null){// This assumes that savedImage is an instance of Texture2D// and that you have already called a function equivalent to// getScreenshot() to set savedImage// NOTE: see sample definition of getScreenshot() method belowbyte[]pngData=savedImage.EncodeToPNG();builder=builder.WithUpdatedPngCoverImage(pngData);}SavedGameMetadataUpdateupdatedMetadata=builder.Build();savedGameClient.CommitUpdate(game,updatedMetadata,savedData,OnSavedGameWritten);}publicvoidOnSavedGameWritten(SavedGameRequestStatusstatus,ISavedGameMetadatagame){if(status==SavedGameRequestStatus.Success){// handle reading or writing of saved game.}else{// handle error}}publicTexture2DgetScreenshot(){// Create a 2D texture that is 1024x700 pixels from which the PNG will be// extractedTexture2DscreenShot=newTexture2D(1024,700);// Takes the screenshot from top left hand corner of screen and maps to top// left hand corner of screenShot texturescreenShot.ReadPixels(newRect(0,0,Screen.width,(Screen.width/1024)*700),0,0);returnscreenShot;}
قراءة لعبة محفوظة
بعد فتح ملف اللعبة المحفوظة، يمكن قراءته لتحميل حالة اللعبة. يتم ذلك من خلال استدعاء ReadBinaryData.
voidLoadGameData(ISavedGameMetadatagame){ISavedGameClientsavedGameClient=PlayGamesPlatform.Instance.SavedGame;savedGameClient.ReadBinaryData(game,OnSavedGameDataRead);}publicvoidOnSavedGameDataRead(SavedGameRequestStatusstatus,byte[]data){if(status==SavedGameRequestStatus.Success){// handle processing the byte array data}else{// handle error}}
حذف لعبة محفوظة
بعد فتح ملف اللعبة المحفوظة، يمكن حذفه. ويتم ذلك من خلال استدعاء الدالة
Delete.
voidDeleteGameData(stringfilename){// Open the file to get the metadata.ISavedGameClientsavedGameClient=PlayGamesPlatform.Instance.SavedGame;savedGameClient.OpenWithAutomaticConflictResolution(filename,DataSource.ReadCacheOrNetwork,ConflictResolutionStrategy.UseLongestPlaytime,DeleteSavedGame);}publicvoidDeleteSavedGame(SavedGameRequestStatusstatus,ISavedGameMetadatagame){if(status==SavedGameRequestStatus.Success){ISavedGameClientsavedGameClient=PlayGamesPlatform.Instance.SavedGame;savedGameClient.Delete(game);}else{// handle error}}
يخضع كل من المحتوى وعيّنات التعليمات البرمجية في هذه الصفحة للتراخيص الموضحّة في ترخيص استخدام المحتوى. إنّ Java وOpenJDK هما علامتان تجاريتان مسجَّلتان لشركة Oracle و/أو الشركات التابعة لها.
تاريخ التعديل الأخير: 2025-07-27 (حسب التوقيت العالمي المتفَّق عليه)
[[["يسهُل فهم المحتوى.","easyToUnderstand","thumb-up"],["ساعَدني المحتوى في حلّ مشكلتي.","solvedMyProblem","thumb-up"],["غير ذلك","otherUp","thumb-up"]],[["لا يحتوي على المعلومات التي أحتاج إليها.","missingTheInformationINeed","thumb-down"],["الخطوات معقدة للغاية / كثيرة جدًا.","tooComplicatedTooManySteps","thumb-down"],["المحتوى قديم.","outOfDate","thumb-down"],["ثمة مشكلة في الترجمة.","translationIssue","thumb-down"],["مشكلة في العيّنات / التعليمات البرمجية","samplesCodeIssue","thumb-down"],["غير ذلك","otherDown","thumb-down"]],["تاريخ التعديل الأخير: 2025-07-27 (حسب التوقيت العالمي المتفَّق عليه)"],[],[],null,["# Saved games in Unity games\n\nThis topics describes how to use saved games for Play Games Services in Unity\ngames.\n\nBefore you start\n----------------\n\n- Set up your project and the Google Play Games plugin for Unity. For details,\n see the [Get started guide](/games/pgs/unity/unity-start).\n\n- Enabled saved games. See the\n [saved games](/games/pgs/console/enable-features#enable_saved_games) for\n details.\n\nDisplay the saved games UI\n--------------------------\n\nThe standard UI for selecting or creating a saved game entry is displayed by\ncalling: \n\n void ShowSelectUI() {\n uint maxNumToDisplay = 5;\n bool allowCreateNew = false;\n bool allowDelete = true;\n\n ISavedGameClient savedGameClient = PlayGamesPlatform.Instance.SavedGame;\n savedGameClient.ShowSelectSavedGameUI(\"Select saved game\",\n maxNumToDisplay,\n allowCreateNew,\n allowDelete,\n OnSavedGameSelected);\n }\n\n public void OnSavedGameSelected (SelectUIStatus status, ISavedGameMetadata game) {\n if (status == SelectUIStatus.SavedGameSelected) {\n // handle selected game save\n } else {\n // handle cancel or error\n }\n }\n\nOpen a saved game\n-----------------\n\nIn order to read or write data to a saved game, the saved game needs to be\nopened. Since the saved game state is cached locally on the device and saved to\nthe cloud, it is possible to encounter conflicts in the state of the saved data.\nA conflict happens when a device attempts to save state to the cloud but the\ndata currently on the cloud was written by a different device. These conflicts\nneed to be resolved when opening the saved game data.\n\nThere are 2 open methods that handle conflict resolution, the first\n**OpenWithAutomaticConflictResolution** accepts a standard resolution strategy\ntype and automatically resolves the conflicts. The other method,\n**OpenWithManualConflictResolution** accepts a callback method to allow the\nmanual resolution of the conflict.\n\nSee [ISavedGameClient](/games/services/unity/v2/api/interface/google-play-games/basic-api/saved-game/i-saved-game-client) for more details\non these methods. \n\n void OpenSavedGame(string filename) {\n ISavedGameClient savedGameClient = PlayGamesPlatform.Instance.SavedGame;\n savedGameClient.OpenWithAutomaticConflictResolution(filename, DataSource.ReadCacheOrNetwork,\n ConflictResolutionStrategy.UseLongestPlaytime, OnSavedGameOpened);\n }\n\n public void OnSavedGameOpened(SavedGameRequestStatus status, ISavedGameMetadata game) {\n if (status == SavedGameRequestStatus.Success) {\n // handle reading or writing of saved game.\n } else {\n // handle error\n }\n }\n\nWrite a saved game\n------------------\n\nOnce the saved game file is opened, it can be written to save the game state.\nThis is done by calling **CommitUpdate**. There are four parameters to\nCommitUpdate:\n\n1. the saved game metadata passed to the callback passed to one of the Open calls.\n2. the updates to make to the metadata.\n3. the actual byte array of data\n4. a callback to call when the commit is complete.\n\n void SaveGame (ISavedGameMetadata game, byte[] savedData, TimeSpan totalPlaytime) {\n ISavedGameClient savedGameClient = PlayGamesPlatform.Instance.SavedGame;\n\n SavedGameMetadataUpdate.Builder builder = new SavedGameMetadataUpdate.Builder();\n builder = builder\n .WithUpdatedPlayedTime(totalPlaytime)\n .WithUpdatedDescription(\"Saved game at \" + DateTime.Now());\n if (savedImage != null) {\n // This assumes that savedImage is an instance of Texture2D\n // and that you have already called a function equivalent to\n // getScreenshot() to set savedImage\n // NOTE: see sample definition of getScreenshot() method below\n byte[] pngData = savedImage.EncodeToPNG();\n builder = builder.WithUpdatedPngCoverImage(pngData);\n }\n SavedGameMetadataUpdate updatedMetadata = builder.Build();\n savedGameClient.CommitUpdate(game, updatedMetadata, savedData, OnSavedGameWritten);\n }\n\n public void OnSavedGameWritten (SavedGameRequestStatus status, ISavedGameMetadata game) {\n if (status == SavedGameRequestStatus.Success) {\n // handle reading or writing of saved game.\n } else {\n // handle error\n }\n }\n\n public Texture2D getScreenshot() {\n // Create a 2D texture that is 1024x700 pixels from which the PNG will be\n // extracted\n Texture2D screenShot = new Texture2D(1024, 700);\n\n // Takes the screenshot from top left hand corner of screen and maps to top\n // left hand corner of screenShot texture\n screenShot.ReadPixels(\n new Rect(0, 0, Screen.width, (Screen.width/1024)*700), 0, 0);\n return screenShot;\n }\n\nRead a saved game\n-----------------\n\nOnce the saved game file is opened, it can be read to load the game state. This\nis done by calling **ReadBinaryData**. \n\n void LoadGameData (ISavedGameMetadata game) {\n ISavedGameClient savedGameClient = PlayGamesPlatform.Instance.SavedGame;\n savedGameClient.ReadBinaryData(game, OnSavedGameDataRead);\n }\n\n public void OnSavedGameDataRead (SavedGameRequestStatus status, byte[] data) {\n if (status == SavedGameRequestStatus.Success) {\n // handle processing the byte array data\n } else {\n // handle error\n }\n }\n\nDelete a saved game\n-------------------\n\nOnce the saved game file is opened, it can be deleted. This is done by calling\n**Delete**. \n\n void DeleteGameData (string filename) {\n // Open the file to get the metadata.\n ISavedGameClient savedGameClient = PlayGamesPlatform.Instance.SavedGame;\n savedGameClient.OpenWithAutomaticConflictResolution(filename, DataSource.ReadCacheOrNetwork,\n ConflictResolutionStrategy.UseLongestPlaytime, DeleteSavedGame);\n }\n\n public void DeleteSavedGame(SavedGameRequestStatus status, ISavedGameMetadata game) {\n if (status == SavedGameRequestStatus.Success) {\n ISavedGameClient savedGameClient = PlayGamesPlatform.Instance.SavedGame;\n savedGameClient.Delete(game);\n } else {\n // handle error\n }\n }"]]