Microsoft Azure PlayFab logo
    • Multiplayer
    • LiveOps
    • Data & Analytics
    • Add-ons
    • For Any Role

      • Engineer
      • Designer
      • Executive
      • Marketer
    • For Any Stage

      • Build
      • Improve
      • Grow
    • For Any Size

      • Solo
      • Indie
      • AAA
  • Runs on PlayFab
  • Pricing
    • Blog
    • Forums
    • Contact us
  • Sign up
  • Sign in
  • Ask a question
  • Spaces
    • PlayStream
    • Feature Requests
    • Add-on Marketplace
    • Bugs
    • API and SDK Questions
    • General Discussion
    • LiveOps
    • Topics
    • Questions
    • Articles
    • Ideas
    • Users
    • Badges
  • Home /
  • API and SDK Questions /
avatar image
Question by JakeKim · May 28, 2018 at 08:06 PM · apisPlayer Dataunity3dsdks

Saving long text data in one UpdatePlayerData call?

Hello,

I'm porting a Unity title 16C4 with Jump. The game has 144 levels, and I'm saving the states for each level in one long string file. When I load it, I parse the string into each level's data and store internally in game's dictionary.

I've been using PlayerPref to save / long the long string file. However, when I try to save the long string file using UpdatePlayerData, I get this error.

Got error setting user data - Invalid input parameters.

I assume the string is too long, so I tried calling UpdatePlayerDate for each value, which gave me this error.

The client has exceeded the maximum API request rate and is being throttled

How can I go about this? It seems I should somehow send the long string file and parse it in the game.

https://community.playfab.com/questions/10755/optimizing-player-data.html

It seems possible in the comment from the link above, as you said "Yes, encoding player data as a JSON object and stringifying that as the data in a player data key/value pair is a very common usage pattern. It would definitely be more efficient in our current data model.", but how could I do this..? Is there any sample for it?

Thanks!

-Jake

Comment

People who like this

0 Show 0
10 |1200 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

2 Replies

· Add your reply
  • Sort: 
avatar image
Best Answer

Answer by Brendan · May 28, 2018 at 09:24 PM

Yes, if you're using the player data model for your saves (as opposed to the Entity model), you'll want to collect that info into very few keys - one, ideally. Can you provide the code snippet showing how you're making the call, and let us know the details of the parameters you're passing in? How long is the total save data string?

Comment

People who like this

0 Show 0 · Share
10 |1200 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image

Answer by JakeKim · May 29, 2018 at 01:20 PM

Here's the sample save file. The real file is longer, but if it is longer than this, it throws invalid parameter error.

rooms2-save-json-string.txt

Here's the part getting and parsing (deserializing) the user data into SortedDictionary<string, string>.

PlayFabClientAPI.GetUserData(request,
			(result) =>
			{
				Debug.Log("Got user data");
				if ((result.Data == null) || (result.Data.Count == 0))
				{
					Debug.Log("No user data available");
				}
				else
				{
					playerData = result.Data;
                   
                    //update your local copy of playerData

                        SortedDictionary<string, string> dataList = PlayFab.Json.PlayFabSimpleJson.DeserializeObject<SortedDictionary<string, string>>(item.Value.Value);

                    }
                }Here's the part exporting the save data. The data used in game is stored in dataList.protected string ExportSaveData(bool isEncrypt = false)
    {
        string serializedReplay = PlayFab.Json.PlayFabSimpleJson.SerializeObject(dataList);
        return serializedReplay;
    }

    //  datalist 
    SortedDictionary<string, string> dataList = new SortedDictionary<string, string>();

It is updating fine with shorter save file, but when I parse it upon receiving back the saved data, it gives me this InvalidCastException: Cannot cast from source type to destination type error.


rooms2-save-json-string.txt (1.7 kB)
Comment

People who like this

0 Show 7 · Share
10 |1200 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Brendan ♦♦ · May 29, 2018 at 10:20 PM 0
Share

What are the details of the invalid parameter error? The errorDetails in the response will tell you specifically what the problem was.

For parsing the data when you retrieve it, what exactly is "item" in your code snippet? What your code shows is that you get the result back, and you set playerData to result.Data. That, then, should be what you deserialize, in order to get the JSON.

avatar image JakeKim Brendan ♦♦ · May 30, 2018 at 12:38 AM 0
Share

Sorry, some line of the code was deleted, here's clean one.

The item variable is just a var in foreach loop to search playerData. I get correct key and value when I print item.Key and item.Value.Value

public void GetPlayerData() {
		GetUserDataRequest request = new GetUserDataRequest()
		{
			PlayFabId = PlayFabId,
			Keys = null 
		};
		PlayFabClientAPI.GetUserData(request,
			(result) =>
			{
				Debug.Log("Got user data");


				if ((result.Data == null) || (result.Data.Count == 0))
				{
					Debug.Log("No user data available");
				}
				else
				{
                    playerData = result.Data;


                    foreach (var item in playerData)
					{
						Debug.Log(item.Key + "<color=orange> = </color>" + item.Value.Value);
                        SortedDictionary<string, string> dataList = PlayFab.Json.PlayFabSimpleJson.DeserializeObject<SortedDictionary<string, string>>(item.Value.Value);


                        foreach(var value in dataList)
                            print("<color=orange>value : </color>" + value);
                    }
                }
	}

avatar image JakeKim JakeKim · May 30, 2018 at 01:10 AM 0
Share

I figured out Deserialization issue! The below code works.

playerData = result.Data;


                    foreach (var item in playerData)
					{
						Debug.Log(item.Key + "<color=orange> = </color>" + item.Value.Value);
                        var dataListTemp = PlayFab.Json.JsonWrapper.DeserializeObject<Dictionary<string, string>>(item.Value.Value);


                        SortedDictionary<string, string> dataList = new SortedDictionary<string, string>(dataListTemp);


                        foreach (var value in dataList)
                            print("<color=orange>value : </color>" + value);
                    }

Now, the only issue left is saving long string into PlayFab via Json.

avatar image JakeKim Brendan ♦♦ · May 30, 2018 at 12:40 AM 0
Share

On line DeserializeObject is called, I get the error below.

InvalidCastException: Cannot cast from source type to destination type. PlayFab.Json.PlayFabSimpleJson.DeserializeObject[SortedDictionary`2] (System.String json, IJsonSerializerStrategy jsonSerializerStrategy) (at Assets/PlayFabSdk/Shared/Internal/SimpleJson.cs:608) PlayFabManager.<GetPlayerData>m__4 (PlayFab.ClientModels.GetUserDataResult result) (at Assets/Scripts/PlayFabManager.cs:101) PlayFab.Internal.PlayFabHttp+<MakeApiCall>c__AnonStorey0`1[PlayFab.ClientModels.GetUserDataResult].<>m__1 () (at Assets/PlayFabSdk/Shared/Internal/PlayFabHttp/PlayFabHTTP.cs:202) PlayFab.Internal.PlayFabWww+<MakeApiCall>c__AnonStorey3.<>m__0 (System.String response) (at Assets/PlayFabSdk/Shared/Internal/PlayFabHttp/PlayFabWWW.cs:139) UnityEngine.Debug:LogException(Exception) PlayFab.Internal.<MakeApiCall>c__AnonStorey3:<>m__0(String) (at Assets/PlayFabSdk/Shared/Internal/PlayFabHttp/PlayFabWWW.cs:143) PlayFab.Internal.<PostPlayFabApiCall>c__Iterator1:MoveNext() (at Assets/PlayFabSdk/Shared/Internal/PlayFabHttp/PlayFabWWW.cs:215) UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr)

avatar image JakeKim Brendan ♦♦ · May 30, 2018 at 12:43 AM 0
Share

And here's the details of errors when I try to save longer string into PlayFab.

First I get this

Got error setting user data UnityEngine.Debug:Log(Object) PlayFabManager:<UpdatePlayerData>m__3(PlayFabError) (at Assets/Scripts/PlayFabManager.cs:73) PlayFab.Internal.<MakeApiCall>c__AnonStorey3:<>m__0(String) (at Assets/PlayFabSdk/Shared/Internal/PlayFabHttp/PlayFabWWW.cs:152) PlayFab.Internal.<PostPlayFabApiCall>c__Iterator1:MoveNext() (at Assets/PlayFabSdk/Shared/Internal/PlayFabHttp/PlayFabWWW.cs:215) UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr)

and this right after

Invalid input parameters UnityEngine.Debug:Log(Object) PlayFabManager:<UpdatePlayerData>m__3(PlayFabError) (at Assets/Scripts/PlayFabManager.cs:74) PlayFab.Internal.<MakeApiCall>c__AnonStorey3:<>m__0(String) (at Assets/PlayFabSdk/Shared/Internal/PlayFabHttp/PlayFabWWW.cs:152) PlayFab.Internal.<PostPlayFabApiCall>c__Iterator1:MoveNext() (at Assets/PlayFabSdk/Shared/Internal/PlayFabHttp/PlayFabWWW.cs:215) UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr)

avatar image Brendan ♦♦ JakeKim · May 30, 2018 at 01:24 AM 0
Share

First, I'd simplify this to a for. Something like:

for (var key in playerData) {
  if (playerData.hasOwnProperty(key)) {
    var keyVal = playerData[key];
}
}

At that point, keyVal contains a UserDataRecord that you can then use to get to the Value, and deserialize it, if you're storing JSON in the data.

I'd also recommend having a look at the way we use the data in the UnicornBattle demo app (https://github.com/PlayFab/UnicornBattle/blob/ff1285d8a13fb3e6f59f8df838a83a1a825258f2/UnicornBattle/Assets/Scripts/PF_StaticsAndHelpers/PF_PlayerData.cs).

avatar image JakeKim · May 30, 2018 at 07:30 AM 0
Share

It's all good now! There's no more error when updating save data, and the data's saving / loading good :) Thanks!

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Navigation

Spaces
  • General Discussion
  • API and SDK Questions
  • Feature Requests
  • PlayStream
  • Bugs
  • Add-on Marketplace
  • LiveOps
  • Follow this Question

    Answers Answers and Comments

    2 People are following this question.

    avatar image avatar image

    Related Questions

    How can I convert the timezone in PlayFab? 1 Answer

    How do POST from php to playfab,How can i do POST from php to playfab 1 Answer

    Why PlayFab don't get Facebook test user's friends? 1 Answer

    The name 'SteamName' does not exist in the current context 1 Answer

    ConsumeItem and stack removal proper practice 1 Answer

    PlayFab

    • Multiplayer
    • LiveOps
    • Data & Analytics
    • Runs on PlayFab
    • Pricing

    Solutions

    • For Any Role

      • Engineer
      • Designer
      • Executive
      • Marketer
    • For Any Stage

      • Build
      • Improve
      • Grow
    • For Any Size

      • Solo
      • Indie
      • AAA

    Engineers

    • Documentation
    • Quickstarts
    • API Reference
    • SDKs
    • Usage Limits

    Resources

    • Forums
    • Contact us
    • Blog
    • Service Health
    • Terms of Service
    • Attribution

    Follow us

    • Facebook
    • Twitter
    • LinkedIn
    • YouTube
    • Sitemap
    • Contact Microsoft
    • Privacy & cookies
    • Terms of use
    • Trademarks
    • Safety & eco
    • About our ads
    • © Microsoft 2020
    • Anonymous
    • Sign in
    • Create
    • Ask a question
    • Create an article
    • Post an idea
    • Spaces
    • PlayStream
    • Feature Requests
    • Add-on Marketplace
    • Bugs
    • API and SDK Questions
    • General Discussion
    • LiveOps
    • Explore
    • Topics
    • Questions
    • Articles
    • Ideas
    • Users
    • Badges