How to access files from cloud save of other players and edit it?

Hi everyone,

I am making a multiplayer card game where users can play game to earn cards and in game assets. Now i have stored all the data related to card in a .txt file and have uploaded it into cloud save for user. Reason for this is because i need multiple details about the card to be saved for example how long did the user have it for, how much they have upgraded their card skill etc

Now I want users to be able to auction their cards for other players to be seen and bought for in app currency. I have achieved to the point where I am able to save txt file and display it.

How can i access cloud data (specifically txt file) for other players and edit it?

Any help is appreciated

1 Like

Hi Rameez,

Actual files (e.g. saved to Cloud Save Files) can only be read and written by the players that own them.

Cloud Save Player Data, supports Access Classes, including Public Data, which other players can read from.

For example, Player A could write data like this:

using SaveOptions = Unity.Services.CloudSave.Models.Data.Player.SaveOptions;

public async void SavePublicData()
{
    var data = new Dictionary<string, object> { { "keyName", "value" } };
    await CloudSaveService.Instance.Data.Player.SaveAsync(data, new SaveOptions(new PublicWriteAccessClassOptions()));
}

And Player B could read it like this:

public async void LoadPublicDataByPlayerId()
{
  var playerId = "JE1unrWOOzzbIwy3Nl60fRefuiVE";
  var playerData = await CloudSaveService.Instance.Data.Player.LoadAsync(new HashSet<string>{"keyName"}, new LoadOptions(new PublicReadAccessClassOptions(playerId)));
  if (playerData.TryGetValue("keyName", out var keyName)) {
      Debug.Log($"keyName: {keyName.Value.GetAs<string>()}");
  }
}

Of course Player B would have to know Player A’s Player ID in this example!

In practice, you would want to define an Index for the key (e.g. in the Unity Dashboard, under Cloud Save) so that when Player A writes to the specified key, other players are able to see it come up when they query for items for sale.

Using a Query from in game looks like this:

public async void QueryPlayerData()
{
  var query = new Query(
    // The first argument to Query is a list of one or more filters, all must evaluate to true for a result to be included
    new List<FieldFilter>
    {
        new FieldFilter("indexedKeyName", "value", FieldFilter.OpOptions.EQ, true),
        new FieldFilter("anotherIndexedKeyName", "otherValue", FieldFilter.OpOptions.NE, true),
    },
    // The second (optional) argument is a list of keys you want to be included with their values in the response
    // This may include keys which are not part of the index, and does not need to include the index keys
    // If you don't specify any, you will still get back a list of IDs for Players that matched the query
    new HashSet<string>
    {
        "indexedKeyName"
    }
  );

  var results = await CloudSaveService.Instance.Data.Player.QueryAsync(query);

  Debug.Log($"Number of results from query: {results.Count}");
  results.ForEach(r =>
  {
      Debug.Log($"Player ID: {r.Id}");
      r.Data.ForEach(d => Debug.Log($"Key: {d.Key}, Value: {d.Value.GetAsString()}"));
  });
}

You can find more examples like this in the Cloud Save SDK Tutorial.

Of course at some point (e.g. when they actually want to “purchase” a card from another player) you can going to need some server authoritative logic to handle the trading between players - either a game server or Cloud Code.

You can find an example of how to interact with Cloud Save from Cloud Code to read and write data across multiple players here:
https://docs.unity.com/ugs/en-us/manual/cloud-code/manual/modules/how-to-guides/cross-player-data#Update_top_5_player_data_using_Cloud_Save

Note: If you don’t want to change how you are currently saving and loading data, you can also use Cloud Code to read data from any player and return it to another player, some advantages of using Access Classes are that you don’t incur costs from running a cloud function every time you do a read operation, and that it will be a faster operation (as you are reading directly from Cloud Save) and ultimately less code may be required, but either approach is fine.

3 Likes

Thanks @IainUnity3D

await CloudSaveService.Instance.Data.Player.SaveAsync(data, new SaveOptions(new PublicWriteAccessClassOptions()));

When i save like this, then this data not showed in web (in cloud.unity.com), but data is saved, and in build it loaded.

Update (crutch):
Im also call SaveAsync() without Options

Hi Antonio!

Ah yes, sorry for any confusion caused there; while Game State data (Custom Items) is fully explorable in the Dashboard, only Player Data in the default Access Class is currently visible as there is no tab in the Dashboard UI to view Public or Protected Player Data.

We appreciate this is tripping folks up and we will be updating the Cloud Save interface in the Dashboard, likely next month, to make it easier to view and manage all Player Data via the Dashboard.

EDIT: This change went live not long after this post - data in all Access Classes for both Player Data and Game Data is now viewable and editable in the Dashboard.

Best regards,

Iain

1 Like