Unity SDK tutorial
This tutorial shows how to use the Cloud Save SDK to save and load data in Unity.
Note: These features are available from version 3 of the Cloud Save SDK.
Using Cloud Save from Unity
You can call the Cloud Save SDK from a C# script within Unity.
- Create a C# MonoBehaviour script within Unity.
- Add code to Save/Load data from Cloud Save (refer to the example below).
- Attach the newly made script to a game object.
- Select Play to run the project to experience Cloud Save in action.
To learn more about scripting in Unity, refer to Creating and Using Scripts.
SDK sample
The CloudSaveSample
script included with the SDK expands on the examples given in this tutorial. You can find the sample in Unity by selecting Package Manager > Cloud Save > Samples.
Example with authentication
The following example demonstrates how to sign in a player with anonymous authentication using the Authentication package, initialize Cloud Save and provides methods that save and load data with Cloud Save.
using UnityEngine;
using Unity.Services.Core;
using Unity.Services.Authentication;
using Unity.Services.CloudSave;
using Unity.Services.CloudSave.Models;
using Unity.Services.CloudSave.Models.Data.Player;
using SaveOptions = Unity.Services.CloudSave.Models.Data.Player.SaveOptions;
using System.Collections.Generic;
public class CloudSaveSample : MonoBehaviour
{
private async void Awake()
{
await UnityServices.InitializeAsync();
await AuthenticationService.Instance.SignInAnonymouslyAsync();
}
public async void SaveData()
{
var playerData = new Dictionary<string, object>{
{"firstKeyName", "a text value"},
{"secondKeyName", 123}
};
await CloudSaveService.Instance.Data.Player.SaveAsync(playerData);
Debug.Log($"Saved data {string.Join(',', playerData)}");
}
public async void LoadData()
{
var playerData = await CloudSaveService.Instance.Data.Player.LoadAsync(new HashSet<string> {
"firstKeyName", "secondKeyName"
});
if (playerData.TryGetValue("firstKeyName", out var firstKey)) {
Debug.Log($"firstKeyName value: {firstKey.Value.GetAs<string>()}");
}
if (playerData.TryGetValue("secondKeyName", out var secondKey)) {
Debug.Log($"secondKey value: {secondKey.Value.GetAs<int>()}");
}
}
}
Player Data
You can view, edit and delete data for player in the Unity Cloud Dashboard.
Save an item
Save one or more items using the SaveAsync
method.
public async void SaveData()
{
var data = new Dictionary<string, object>{{"keyName", "value"}};
await CloudSaveService.Instance.Data.Player.SaveAsync(data);
}
You can save data in the Public Access Class, if you want other players to be able to read that data.
public async void SavePublicData()
{
var data = new Dictionary<string, object>{{"keyName", "value"}};
await CloudSaveService.Instance.Data.Player.SaveAsync(data, new SaveOptions(new PublicWriteAccessClassOptions()));
}
Fetch data
Get keys and values stored as Player Data using the LoadAsync
method.
public async void LoadData()
{
var playerData = await CloudSaveService.Instance.Data.Player.LoadAsync(new HashSet<string>{"keyName"});
if (playerData.TryGetValue("keyName", out var keyName)) {
Debug.Log($"keyName: {keyName.Value.GetAs<string>()}");
}
}
You can get keys and values for data in the Public and Protected Access Classes.
public async void LoadPublicData()
{
var playerData = await CloudSaveService.Instance.Data.Player.LoadAsync(new HashSet<string>{"keyName"}, new LoadOptions(new PublicReadAccessClassOptions()));
if (playerData.TryGetValue("keyName", out var keyName)) {
Debug.Log($"keyName: {keyName.Value.GetAs<string>()}");
}
}
public async void LoadProtectedData()
{
var playerData = await CloudSaveService.Instance.Data.Player.LoadAsync(new HashSet<string>{"keyName"}, new LoadOptions(new ProtectedReadAccessClassOptions()));
if (playerData.TryGetValue("keyName", out var keyName)) {
Debug.Log($"keyName: {keyName.Value.GetAs<string>()}");
}
}
You can read (but not write to) data in the Public Access Class of another player by passing a Player ID.
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>()}");
}
}
Delete an item
Delete items using the DeleteAsync
method.
public async void DeleteData()
{
await CloudSaveService.Instance.Data.Player.DeleteAsync("key");
}
Get a list of keys
Use the ListAllKeysAsync
method to get a list of keys.
You can also fetch metadata, such as the last time a key was modified.
public async void ListKeys()
{
var keys = await CloudSaveService.Instance.Data.Player.ListAllKeysAsync();
for (int i = 0; i < keys.Count; i++)
{
Debug.Log(keys[i].Key);
}
}
You can also list keys for data in the Public and Protected Access Classes.
public async void ListKeys()
{
var keys = await CloudSaveService.Instance.Data.Player.ListAllKeysAsync(
new ListAllKeysOptions(new PublicReadAccessClassOptions())
);
for (int i = 0; i < keys.Count; i++)
{
Debug.Log(keys[i].Key);
}
}
public async void ListKeys()
{
var keys = await CloudSaveService.Instance.Data.Player.ListAllKeysAsync(
new ListAllKeysOptions(new ProtectedReadAccessClassOptions())
);
for (int i = 0; i < keys.Count; i++)
{
Debug.Log(keys[i].Key);
}
}
Query Player Data
Query values for any indexed key in the Player Data Public Access Class.
Data saved before an index was created (or that is too large to be indexed) will not be returned from a query.
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, new QueryOptions());
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()}"));
});
}
Game Data
You can save and load Game Data that is not player-specific by using a Custom Item.
Game clients can only read custom items. They cannot create, modify or delete Custom items. Custom Items can be written to using Cloud Code, a game server, using the HTTP API or from the Unity Cloud Dashboard.
Fetch data
Fetch all data for a Custom Item using LoadAllAsync
.
public async void LoadCustomItemData()
{
var customItemId = 'my-custom-item';
var customItemData = await CloudSaveService.Instance.Data.Custom.LoadAllAsync(customId);
foreach (var customItem in customItemData)
{
Debug.Log($"Key: {customItem.Key}, Value: {customItem.Value.Value}");
}
}
Query Custom Items
Query values for any indexed key in the Custom Item Default Access Class.
Data saved before an index was created (or that is too larged to be indexed) will not be returned from a query.
public async void QueryCustomItems()
{
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.Custom.QueryAsync(query);
Debug.Log($"Number of results from query: {results.Count}");
results.ForEach(r =>
{
Debug.Log($"Custom Item ID: {r.Id}");
r.Data.ForEach(d => Debug.Log($"Key: {d.Key}, Value: {d.Value.GetAsString()}"));
});
}
Player Files
Cloud Save Files provides a way to store large save files (up to 1 GB) in any format and to access save game files across multiple devices / platforms.
Save Player File
Read in a locally saved file on a device and save to Cloud Save using the SaveAsync
method.
public async void SavePlayerFile()
{
byte[] file = System.IO.File.ReadAllBytes("fileName.txt");
await CloudSaveService.Instance.Files.Player.SaveAsync("fileName", file);
}
Delete Player File
Delete a player file using the DeleteAsync
method.
public async void DeletePlayerFile()
{
await CloudSaveService.Instance.Files.Player.DeleteAsync("fileName");
}
List Player Files
Use the ListAllAsync
method to get a list of names of all files for a player.
public async void ListPlayerFiles()
{
List<FileItem> files = await CloudSaveService.Instance.Files.Player.ListAllAsync();
for (int i = 0; i < files.Count; i++)
{
Debug.Log(files[i]);
}
}
Get Player File as a byte array
Get player file as a byte array with the LoadBytesAsync
method.
public async void GetPlayerFileAsByteArray()
{
byte[] file = await CloudSaveService.Instance.Files.Player.LoadBytesAsync("fileName");
}
Get Player File as a stream
Get player file as a stream with the LoadStreamAsync
method.
public async void GetPlayerFileAsStream()
{
Stream file = await CloudSaveService.Instance.Files.Player.LoadStreamAsync("fileName");
}
Get Player File Metadata
Retrieves the metadata (size, date last modified and created, key, content type, and current WriteLock) of a single player file with the GetMetadataAsync
method.
public async void GetPlayerFileMetadata()
{
var metadata = await CloudSaveService.Instance.Files.Player.GetMetadataAsync("fileName");
Debug.Log(metadata.Key);
Debug.Log(metadata.Size);
Debug.Log(metadata.ContentType);
Debug.Log(metadata.Created);
Debug.Log(metadata.LastModified);
Debug.Log(metadata.WriteLock);
}
You can use the Unity Cloud Dashboard to access the files of an individual player. You can find these files under the player details in the Cloud Save module.
Error handling
Use the error code or type that the SDK returns for a method in your error handling logic.
Avoid using error messages as they might change in the future.