Cloud Save - Overview¶
Beamable's Cloud Save feature provides secure, cross-platform storage for player game data. It enables players to seamlessly save their progress and access it across multiple devices, ensuring data persistence and continuity throughout their gaming experience.
Key Benefits: - Cross-Device Sync: Players can switch between devices without losing progress - Automatic Conflict Resolution: Handles data conflicts when multiple saves exist - Secure Storage: Encrypted cloud storage with up to 5MB per file - Offline Support: Local caching ensures gameplay continues without connectivity
Migrating from Old Cloud Save Service
If your application uses the old Cloud Save you must keep in mind some specifics when migrating to the new one:
• You cannot initialize both Services at the same time, the first one initialized will lock the other to be used.
• Both services share the same cloud storage, but the saved data are stored in different system paths. When you switch to the new one, it will automatically download your data.
Cloud Save API¶
Unlike many Beamable Features, Cloud Save does not require the usage of a specific Beamable Feature Prefab. The main entry point to this feature is C# programming.
Learning Fundamentals
For comprehensive learning about Beamable fundamentals, we recommend the following resources:
• See Beamable: Asynchronous Programming for more info
Note: This API is demonstrated in the CloudSavingServiceExample.cs below.
| Method Name | Detail |
|---|---|
| Init | Initializes the CloudService using the configurations from PlayerCloudSavingConfiguration. Starts resolving the save storages and downloading cloud data to local device. By default, it uses a default instance of PlayerCloudSavingConfiguration. See this link to see how to override it. Note: This accepts an optional pollingIntervalSecs parameter which determines how often the service will scan for local file changes |
| ReInit | Re-initializes the CloudService. Stopping all routines, upload, and download requests to restart the system. Note: This accepts an optional pollingIntervalSecs parameter which determines how often the service will scan for local file changes |
| ServiceStatus | Returns a CloudSaveStatus enum with the current Cloud Saving Service Status (Inactive, Initialized, Initializing, and ConflictedData) |
| LocalDataFullPath | Returns the Full Path where the Cloud Save Files are stored in the local device. This Property will return an exception if the CloudSaving is Inactive. |
| OnManifestUpdated | This event is invoked any time that the Cloud Manifest is updated. |
| OnCloudSavingError | This event is invoked any time that an Error Occurs to the Cloud Saving. |
| ForceUploadLocalData | Forces an Upload of Local Data to the Cloud, ignoring any conflicts that may have and using Local Save. |
| ForceDownloadCloudData | Forces a Download of Cloud Data to Local Device, ignoring any conflicts that may have and using Cloud Save. |
| GetDataConflictDetails | If the Service was initialized and it wasn't possible to resolve the conflict between cloud and local. You can use this function to get the details about these conflicts. |
| ResolveDataConflict | You need to use this function to solve a conflict that happened between a local or cloud file. This function takes the conflict detail and an enum of which data to use. Note: If you need to merge data between local and cloud saves, you can manually save the local file and mark to use the local file as the conflict resolve type. |
| SaveData | It allows you to save your data using the Service, allowing you to properly save the file without needing to get the full file path or handle file name sanitization. This function has 3 overrides which you can save the data as byte, string, or serialize a class/struct to the file. Note: The serialize save by default uses JsonUtility to serialize, but you can override it by changing the PlayerCloudSavingConfiguration.CustomSerializer. |
| LoadDataString LoadDataByte LoadData |
Loads the Local Data using the Service, allowing you to properly load the file without needing to get the full file path or handle file name sanitization. It returns the content of the file depending on which LoadData call is used. Note: The LoadData |
| Update | This function allows you to do Update operations to the CloudSaveService and apply them only once, reducing API calls to the backend. The possible operations for the CloudDataUpdateBuilder are: - SaveData - ArchiveSaveData - RenameSaveData - ForgetSaveData |
| SetConflictResolverOverride | This function allows you to Override the ConflictResolver by another ConflictResolver delegate. This function is another option than the PlayerCloudSavingConfiguration.HandleConflicts which allows you to change the Conflict resolution depending on the current application scope. |
Cloud Data Manifest¶
When changes are detected by the service and finished saving locally, the Local Cloud Data Manifest will be updated. Therefore, after updating data to Cloud Save, The local manifest will be updated to match the manifest from Cloud.
Cloud Saved files are written to an object store that is managed by the Cloud Saving service. The key of the object is the MD5 checksum of the content in the file, this is done to preserve the history of the files.
The manifest tracks the MD5 checksum(etag) of the file and the common name(key) of the file, so we can fetch the object by its MD5 checksum and write it to disk using the common name.
Json Format
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
Changing Service Configuration¶
It is possible to override and adapt the service to best adapt to your application, the possible configurations are available in the PlayerCloudSavingConfiguration class. By default, the system will use a new instance of it if it has default values. To change their values you need to modify dependency to the Beamable Dependency Injection. The final result should look like this:
CustomRegisterExample.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | |
Syncing Of Data¶
The downloading operation uses Unity's DownloadHandlerFile. If the file is new, it will be saved directly to the /data/ Folder. If the file has a conflict it will be first saved to the /temp/ folder, if the resolver chooses to use the Cloud Save, it'll be moved to the /data/ folder, if not, it will be archived.
Note If the destination files are kept open by some unrelated system during the syncing process, the CloudSavingService will reattempt several times. Upon any ultimate failure, an IOException will be thrown.
Storage Of Data¶
Data is stored in within Unity's Application.persistentDataPath and prefixed with the Customer ID (CID), Project ID (PID), and Player ID (PlayerId). This is to ensure data is scoped to a game and a player. The full path is available at ICloudSavingService.LocalDataFullPath.
There are two options for detecting changes to the Local Save files, the first one, which is the Default, is to detect changes at runtime from the manifest and the other is to use the AutoCloud feature, which detects the folder path directly.
Detecting Changes from Local Manifest¶
For this option, whenever a File is Saved using the SaveData functions through the service, which could be from ICloudSavingService or from the CloudDataUpdateBuilder it will update the local manifest automatically. After the polling interval taken on the Init function, it will automatically upload any changes to the cloud service. If you write a file directly to the /data/ folder, this option will not detect it automatically.
Detecting Changes from Data Folder (AutoCloud)¶
The AutoCloud feature will automatically check the /data/ folder checking for changes every polling interval and automatically uploading any changes to the cloud service. It also updates the local manifest automatically. This is slightly more expensive than the first option as it needs to keep generating the checksum for the file every polling interval, but it allows you to write the file manually to the data folder.
To enable this option, you will need to add or update the Custom dependency for PlayerCloudSavingConfiguration and set the property UseAutoCloud to true. Check the section Changing Service Configuration to see how to properly add it.
Error Handling¶
Is possible that some errors occur when trying to download a saved file. The system automatically will try to download the file 10 times, if the 10th retry fails, the system will return an error. Which can be anything from no connection to a file not found. By default, the service will use the DefaultRecover, which will not throw an exception if the file cannot be found in storage, ignoring its download and using the local reference as the new one. If there is any other error, it will throw the exception.
If you want to change its behavior, you will need to add or update the Custom dependency for PlayerCloudSavingConfiguration and set the property HandleDownloadFileError. Check the section Changing Service Configuration to see how to properly add it.
Data Limitations¶
There is a limit of 5MB per cloud save file.
Data Management Via Portal¶
The Portal allows the game maker to manage player data as well. Search for a player, select the CloudData tab, and navigate to the player data.
Some common use-cases for game makers include;
- Debugging - Play as a customer's player data to test and investigate reported issues
- Support - Make minor edits to a player data and hot-upload it for the customer
Here are the major operations that can be performed against the player data.
| Name | Detail |
|---|---|
| 1. Search | A content-based search of the player data; search for contained terms. |
| 2. Download | Allows a game maker with admin privileges to download a copy of a single object of player data. |
| 3. Upload | Replace an object of player data with a file that has the same name. |
Gotchas
Here are some common issues and solutions:
• While Beamable supports minor edits to the player data from the portal, restoring the a customer's player data completely to a historic backup state is not supported.
• The CloudSavingService does not support multiple game sessions using the same user. If there are multiple sessions for the same user, for the same game, this will create an infinite ping/pong effect. E.g. Device A will send updates that Device B will fetch, which will send updates that Device A will fetch, etc...
• Manually deleting content from the LocalCloudDataFullPath is not supported
• Old Cloud Save Service doesn't support multiple files with the same content. If you want files with the same content (for example a backup file), please add a tag to differentiate them or use the New Cloud Save Service.
Sample Code¶
Here is a sample code that demonstrates how to use the Cloud Save Service in Unity. This is a sample code that shows all the different options for using the Cloud Save Service. Note that this is an example for reference only. We do not recommend copying directly the functions used in the sample.
CloudSavingServiceExample.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 | |
