playgameservices / play-games-plugin-for-unity

Google Play Games plugin for Unity
Other
3.44k stars 959 forks source link

Saved Games dom't work right. Problem with ConflictResolutionStrategy, DataSource or SavedGameMetadataUpdate. #3051

Closed AnderX003 closed 3 years ago

AnderX003 commented 3 years ago

Hi everyone! I'm implementing Saved Games in my game (achievements and leaderboards work fine already).

Here is my problem: When I save my data to cloud for the first time everything is okay and I can successfully read it from cloud. But if I write data to cloud again and try to read data from cloud I get my old data.

I guess my problem is ConflictResolutionStrategy. I don't actually know how these stategys work, but I tried many differend ways and got the same result. Also, I don't know what DataSource do, but I tried DataSource.ReadNetworkOnly and DataSource.ReadCacheOrNetwork as well, but it didn't help me.

My code:

            private static bool isProcessing;
            private const string dataName = "bests";

            public static void WriteDataToCloud()
            {
                OpenConnection(dataName, WriteOnConnectionOpen);
            }

            private static void ReadDataFromCloud()
            {
                OpenConnection(dataName, ReadOnConnectionOpen);
            }

            private static void OpenConnection(string name,
                Action<SavedGameRequestStatus, ISavedGameMetadata> onConnectionOpen)
            {
                if (!Social.localUser.authenticated) return;
                isProcessing = true;
                Debug.Log("Opening connection");
                PlayGamesPlatform.Instance.SavedGame.OpenWithAutomaticConflictResolution(name,
                    DataSource.ReadCacheOrNetwork,
                    ConflictResolutionStrategy.UseMostRecentlySaved, onConnectionOpen);
            }

            private static void WriteOnConnectionOpen(SavedGameRequestStatus status, ISavedGameMetadata metadata)
            {
                if (status != SavedGameRequestStatus.Success) return;
                Debug.Log("Connection opened to write");
                int[] localData = //my data
                Debug.Log(localData.Aggregate("", (current, i) => current + (i + " ")));
                byte[] data = new byte[localData.Length * sizeof(int)];
                Buffer.BlockCopy(localData, 0, data, 0, data.Length);
                SavedGameMetadataUpdate updatedMetadata = new SavedGameMetadataUpdate.Builder()
                    .WithUpdatedDescription("Saved at " + DateTime.Now.ToString(CultureInfo.InvariantCulture))
                    .Build();

                PlayGamesPlatform.Instance.SavedGame.CommitUpdate(metadata, updatedMetadata, data,
                    (savedGameRequestStatus, savedGameMetadata) =>
                    {
                        isProcessing = false;
                        if (savedGameRequestStatus == SavedGameRequestStatus.Success)
                            Debug.Log("Written to cloud");
                    });
            }

            private static void ReadOnConnectionOpen(SavedGameRequestStatus status, ISavedGameMetadata metadata)
            {
                PlayGamesPlatform.Instance.SavedGame.ReadBinaryData(metadata,
                    (savedGameRequestStatus, data) =>
                    {
                        isProcessing = false;
                        if (status != SavedGameRequestStatus.Success) return;
                        Debug.Log("Connection opened to read");
                        PlayerPrefs.SetInt("DataWasReadFromCloud", 1);
                        int[] convertedData = new int[data.Length / sizeof(int)];
                        Buffer.BlockCopy(data, 0, convertedData, 0, convertedData.Length);
                        //my logic
                    });
            }

So I got a few questions:

AnderX003 commented 3 years ago

So I found the solution of this bug. Eventually I realized that byte[] data = new byte[localData.Length * sizeof(int)]; Buffer.BlockCopy(localData, 0, data, 0, data.Length); doesn't work right for converting from int[] to byte[] and from byte[] to int[]. I found those methods on the internet and added them to my game and everything worked perfectly:

private static int[] ConvertByteArrayToIntArray(byte[] inputElements)
{
    int[] myFinalIntegerArray = new int[inputElements.Length / 4];
    for (int cnt = 0; cnt < inputElements.Length; cnt += 4)
    {
        myFinalIntegerArray[cnt / 4] = BitConverter.ToInt32(inputElements, cnt);
    }
    return myFinalIntegerArray;
}

public static byte[] ConvertIntArrayToByteArray(int[] inputElements)
{
    byte[] myFinalBytes = new byte[inputElements.Length * 4];
    for(int cnt = 0 ; cnt<inputElements.Length; cnt ++)
    {
        byte[] myBytes = BitConverter.GetBytes(inputElements[cnt]);
        Array.Copy(myBytes, 0, myFinalBytes, cnt*4, 4);
    }
    return myFinalBytes;
}