Unity SDK tutorial
Use the Cloud Save Software Development Kit to save and load player data, game data, and files in your Unity project.
Read time 5 minutesLast updated 2 days ago
This tutorial shows how to use the Cloud Save SDK to save and load data in Unity.
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.
SDK sample
TheCloudSaveSampleExample 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 Dashboard.Save an item
Save one or more items using theSaveAsyncYou can save data in the Public Access Class, if you want other players to be able to read that data.public async void SaveData(){ var data = new Dictionary<string, object>{{"keyName", "value"}}; await CloudSaveService.Instance.Data.Player.SaveAsync(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 theLoadAsyncYou can get keys and values for data in the Public and Protected Access Classes.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>()}"); }}
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>()}"); }}
You can read (but not write to) data in the Public Access Class of another player by passing a Player ID.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>()}"); }}
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 theDeleteAsyncpublic async void DeleteData(){ await CloudSaveService.Instance.Data.Player.DeleteAsync("key");}
Get a list of keys
Use theListAllKeysAsyncYou 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(); 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 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.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.Fetch data
Fetch all data for a Custom Item usingLoadAllAsyncpublic async void LoadCustomItemData(){ var customItemId = "my-custom-item"; var customItemData = await CloudSaveService.Instance.Data.Custom.LoadAllAsync(customItemId); 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.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 theSaveAsyncpublic async void SavePlayerFileBytes(){ byte[] fileBytes = System.IO.File.ReadAllBytes("fileName.txt"); await CloudSaveService.Instance.Files.Player.SaveAsync("fileByteName", fileBytes);}
public async void SavePlayerFileStream(){ Stream fileStream = System.IO.File.OpenRead("fileName.txt"); await CloudSaveService.Instance.Files.Player.SaveAsync("fileStreamName", fileStream);}
Save Player File options
TheSaveAsyncSaveOptionsWriteLockRequestTimeoutWriteLockRequestTimeoutpublic async void SavePlayerFileWithOptions(){ Stream file = System.IO.File.OpenRead("fileName.txt"); await CloudSaveService.Instance.Files.Player.SaveAsync("fileName", file, new Unity.Services.CloudSave.SaveOptions { WriteLock = "27efb4b1b27a732c0e32a6229ec52776" RequestTimeout = 60 });}
Delete Player File
Delete a player file using theDeleteAsyncpublic async void DeletePlayerFile(){ await CloudSaveService.Instance.Files.Player.DeleteAsync("fileName");}
List Player Files
Use theListAllAsyncpublic 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 theLoadBytesAsyncpublic 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 theLoadStreamAsyncpublic 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 theGetMetadataAsyncYou can use the Unity Dashboard to access the files of an individual player. You can find these files under the player details in the Cloud Save module.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);}