Handling Conflicts & Synchronization
Cloud Services in Essential Kit let you save and retrieve simple key-value pairs that automatically sync between local and cloud storage. It’s designed to be simple, fast, and reliable – with built-in support for detecting conflicts during synchronization.
Let’s explore how it works using an example.
🎮 Use Case: Saving Player Settings
Imagine you’re working on a game where the player can configure their settings – like the selected language, sound volume, or preferred difficulty. You want to store these preferences in the cloud, so that if the player installs the game on another device, their settings come along.
Step 1: Save Settings to Cloud
Let’s assume the player updates their preferred language setting.
CloudServices.SetString("player.language", "en");
This will immediately update the device copy with the value "en"
for the key player.language
. At this point, the value is still only available locally – it has not yet been pushed to the cloud.
✅ Tip: All
Set*
methods update the device copy immediately.
Step 2: Synchronize with Cloud
When you want to push or pull the latest data to/from the cloud, call:
CloudServices.Synchronize();
This will:
Fetch the latest copy of cloud data.
Compare the local and cloud versions.
Detect if any keys have changed in both locations since last sync.
If a conflict is detected (i.e., both local and cloud versions were modified), Essential Kit overwrites the local value with the cloud copy and triggers an event CloudServices.OnSavedDataChange
Step 3: Handle Conflict in OnSavedDataChange
OnSavedDataChange
You can listen for this event and inspect which keys had conflicting values:
void OnSavedDataChange(CloudServicesSavedDataChangeResult result)
{
if (result.ChangedKeys == null)
{
return;
}
//📌 Important: CloudServices.GetString(key) now returns the cloud value because the device copy was overwritten.
for (int i = 0; i < result.ChangedKeys.Length; i++)
{
string key = result.ChangedKeys[i];
string cloudValue;
string previousDeviceValue;
// Retrieve the latest cloud value and the device snapshot saved before the overwrite
CloudServicesUtility.TryGetCloudAndLocalCacheValues(key, out cloudValue, out previousDeviceValue, "default");
Debug.LogFormat("[{0}] Key: {1}\n [Cloud Value]: {2}\n [Previous Device Value]: {3}", i, key, cloudValue, previousDeviceValue);
// Decide what to do: keep the cloud value or restore the previous device value
if (ShouldKeepLocalValue(key, previousDeviceValue, cloudValue))
{
CloudServices.SetString(key, previousDeviceValue);
}
}
}
Step 4: Finalize with SynchronizeComplete
SynchronizeComplete
After the sync is completed (and any conflict resolution is done), the SynchronizeComplete
event fires:
CloudServices.OnSynchronizeComplete += (result) =>
{
Debug.Log($"Cloud sync complete. Success: {result.Success}");
};
If you restored a value during conflict resolution using SetString
, the updated value will be pushed to the cloud on the next sync cycle – either manually triggered or automatically (e.g., app going to background).
⚡ Quick Recap
SetString("key", value)
Immediately updates the device copy
Synchronize()
Syncs data, resolves conflicts, and fires events
OnSavedDataChange
Fires after a conflict, providing changed keys and the reason
TryGetCloudAndLocalCacheValues
Lets you inspect both the cloud value and the previous device value
SetString(...)
inside event
Lets you restore the preferred value before the next sync
OnSynchronizeComplete
Fires after sync and conflict resolution is done
Example Conflict Flow
Let’s say:
Player changes
"player.language"
to"en"
locally.On another device, the same key is changed to
"fr"
.Player syncs both devices.
During sync, the cloud value "fr"
is fetched and overwrites the local "en"
, triggering OnSavedDataChange
. Now you can use the utility function CloudServicesUtility.TryGetCloudAndLocalCacheValues
to retrieve both the cloud value ("fr"
) and the old local value ("en"
), allowing you to decide whether to keep the cloud version or restore your original local data.
Last updated
Was this helpful?