# 6. Cloud Save Pitfalls Part of [[Cloud Save and Unity Services]]. Prev: [[5. Worked Example High Scores Mirror]]. ## Blocking the local save on a network error The contract is: disk first, mirror after, catch `CloudSaveException` (and friends). A thrown upload that fails the `Saved` handler or the save button is a broken offline game. ## Silent overwrite `SaveAsync(IDictionary<string, object>)` and `new SaveItem(value, null)` both **skip** write-lock validation. Fine for a first create or a player-confirmed force. Not fine as the only path on startup. Compare `savedUtcTicks` and ask. ## Cloud always wins A bus ride of offline play will lose to a stale cloud copy. Offer a choice. ## A second schema for the cloud If the file is JSON and the cloud item is a different DTO, they will drift. Store the **same string**. Prefer `GetAsString()` as High Scores Part 4 already does. `GetAs<T>()` is official in 3.4.2; using it here is how you accidentally deserialize a different shape than `JsonUtility`. ## Bad keys Spaces, slashes, punctuation outside the official set (alphanumeric, dash, underscore, max 255) show up as validation errors. Use `slot_0`. ## `DeleteAllAsync` on a player button Official: deletes **all** keys, no write-lock validation. Keep it off the options menu in this course. ## Missing key treated as an exception you invented `LoadAsync` returns a dictionary. A missing key is absence. Do not wrap it in a custom "not found throw" that your startup compare then treats as a hard failure. ## Write lock on create / stale lock on update Official: omit the lock when **creating**. On update, send the lock you just loaded (or the one `SaveAsync` just returned). Reusing a lock from last week's session after several uploads is a textbook `CloudSaveConflictException`. ## New anonymous PlayerId, "empty cloud" Clearing player data, a second machine, or a second Play Mode identity is a **new player**. The old `slot_0` is still on the old ID. Do not "fix" this by deleting keys. ## Two `UgsBootstrap` classes Cloud Save and Multiplayer Services should share one initialize / sign-in path ([[1. Services Project and Authentication]]). Two copies will eventually disagree about `IsSignedIn`. ## `SaveAsync` in `Update` Rate limits are official (`CloudSaveRateLimitedException`). Upload on `Saved` and on an explicit "Sync" / startup compare. ## Economy / IAP / Files API feature creep Out of scope. Files exist in 3.4.2; confirm the API if you truly need a binary. Do not invent method names, and do not add `com.unity.purchasing` to "store the slot." ## Secrets and Project ID confusion Dashboard keys and service accounts do not belong in Git ([[Version Control]]). A typo'd Project ID in another teammate's Editor looks like "Cloud Save is down." ## "It uploaded in the Editor" The assignment includes an offline test and a conflict test, not only a happy-path Play Mode save. ## Sources - https://docs.unity.com/en-us/cloud-save/concepts/write-locks - https://docs.unity3d.com/Packages/[email protected]/api/Unity.Services.CloudSave.Internal.IPlayerDataService.html - [[High Scores, Saves and Player Stats]]