A lot of developers trip up on how best to seralize and deseralize data when using Unity Cloud Save, specifically they often save objects as strings rather saving them directly as objects and sometimes run into problems as a result.
This happens either because people are used to how versions of the Cloud Save SDK used to work, because they don't realise that you can save objects without converting them to a string, or because they don't realise that the approach they are using causes them to be seralized.
If saved as a string instead of directly as an object, data can be more complicated to work with than it needs to be, you won't be able to use features like filters to query on the saved data and if you are viewing in somewhere like the Unity Cloud Dashboard it will just be rendered as a single long escaped string (which is hard to read and even harder to edit).
The sample that comes with the Unity Cloud Save SDK has good examples of how to load and save objects that includes appropriate error handling, but for quick reference (without any error handling!) some people might find this example helpful.
These are the models that define the objects we will be saving and loading.
using System;
using System.Collections.Generic;
[Serializable]
public class SampleObject
{
public string Name;
public List<SampleItem> Items = new List<SampleItem>();
}
public class SampleItem
{
public string ItemName;
public int ItemInt;
public float ItemFloat;
public bool ItemBool;
}
This code includes an example of how to write locks when saving data, to ensure it hasn't already been modified by another process or thread between reading and writing. If you don't use write locks, it will just force save.
using System.Collections.Generic;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Unity.Services.Authentication;
using Unity.Services.CloudSave;
using Unity.Services.CloudSave.Models;
using Unity.Services.Core;
using UnityEngine;
public class CloudSaveObjectExample: MonoBehaviour
{
private async void Awake()
{
// Sign in with Unity Authentication
await UnityServices.InitializeAsync();
await AuthenticationService.Instance.SignInAnonymouslyAsync();
// Create a new sample object
SampleObject newSampleObject = new SampleObject { Name = "My sample object" };
newSampleObject.Items.Add(
new SampleItem
{
ItemName = "Item 1",
ItemInt = 1,
ItemFloat = 3.14f,
ItemBool = true
}
);
// Save the object to Cloud Save Player Data, get a write lock back
string writeLock = await SaveSampleObject("myKey", newSampleObject);
Debug.Log($"Saved {JsonConvert.SerializeObject(newSampleObject)} and got write lock {writeLock}");
// Load sample object from Cloud Save Player Data
SampleObject sampleObject = await LoadSampleObject<SampleObject>("myKey");
Debug.Log($"Loaded {JsonConvert.SerializeObject(sampleObject)}");
// Modify the item we just got back from Cloud Save
sampleObject.Items.Add(
new SampleItem
{
ItemName = "Item 2",
ItemInt = 2,
ItemFloat = 4.28f,
ItemBool = false
}
);
// Save the modified item back to Cloud Save
writeLock = await SaveSampleObject("myKey", sampleObject, writeLock);
Debug.Log($"Saved {JsonConvert.SerializeObject(sampleObject)} and got new write lock {writeLock}");
}
private async Task<string> SaveSampleObject(string key, object value, string writeLock = null)
{
Dictionary<string, string> result = await CloudSaveService.Instance.Data.Player.SaveAsync(
new Dictionary<string, SaveItem> { { key, new SaveItem(value, writeLock) } }
);
return result[key]; // return write lock
}
private async Task<T> LoadSampleObject<T>(string key)
{
var results = await CloudSaveService.Instance.Data.Player.LoadAsync(new HashSet<string> { key });
if (results.TryGetValue(key, out var item))
{
return item.Value.GetAs<T>();
}
else
{
return default;
}
}
}
The saved data will look something like like this when viewed in the Unity Cloud Dashboard (i.e. nicely formatted and easily editable, strings won't be double-escaped):
- You don't need to serialize objects first, the Unity Cloud Save SDK will do that for you
- Data in Cloud Save can be Strings, Numbers, Arrays, Booleans or Objects
- Objects can be nested and you can have arrays of objects
See the Unity Cloud Save tutorial for more information.