> For the complete documentation index, see [llms.txt](https://assetstore.essentialkit.voxelbusters.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://assetstore.essentialkit.voxelbusters.com/features/cloud-services/playmaker/use-cases/use-case-2-multi-device-sync.md).

# Multi-Device Progress Sync

## Goal

Load saved data when app starts and listen for changes from other devices.

## Actions Required

| Action                         | Purpose                                 |
| ------------------------------ | --------------------------------------- |
| CloudServicesGetValue          | Load saved data                         |
| CloudServicesOnSavedDataChange | Listen for remote updates               |
| CloudServicesGetChangedKeys    | Read changed key list (optional helper) |

## Variables Needed

* playerLevel (Int)
* totalScore (Int)
* changedKeys (Array: String) - PlayMaker Array (set element type to String)
* changeReason (Enum: CloudSavedDataChangeReasonCode)

## Implementation Steps

### 1. State: LoadProgress (On App Start)

**Action:** CloudServicesGetValue

* **Inputs:**
  * key: "player\_level"
  * valueType: Int
* **Outputs:**
  * value → playerLevel

Repeat for each key you want to load.

### 2. State: ListenForChanges

**Action:** CloudServicesOnSavedDataChange

* **Outputs:**
  * changedKeys → changedKeys array
  * changeReason → changeReason
* **Events:**
  * dataChangedEvent → HandleRemoteChange

### 3. State: HandleRemoteChange

Use the `changedKeys` array from `CloudServicesOnSavedDataChange` directly, or call `CloudServicesGetChangedKeys` to fetch the same cached list in a later state. Loop `keyIndex = 0..changedKeys.Length-1` and read each key using PlayMaker Array Get.

1. If you need conflict handling, call `CloudServicesGetCloudAndLocalCacheValues(keyName)` to get both values:
   * decide your policy (cloud wins / local wins / max wins / prompt user)
2. Otherwise, just reload from cloud:
   * If keyName == "player\_level" → `CloudServicesGetValue("player_level", valueType:Int)` and update `playerLevel`
   * If keyName == "total\_score" → `CloudServicesGetValue("total_score", valueType:Int)` and update `totalScore`

If you don’t want a loop, you can also directly use PlayMaker Array actions (Array Get / Array Contains) on `changedKeys`.

## Conflict Resolution Strategies

**Last Write Wins:** Use remote value always **Highest Wins:** Compare local vs remote, keep higher value **Manual Merge:** Prompt user to choose


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://assetstore.essentialkit.voxelbusters.com/features/cloud-services/playmaker/use-cases/use-case-2-multi-device-sync.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
