Skip to content

Releases: buck-co/save-async

v0.14.0

27 Oct 18:46

Choose a tag to compare

[0.14.0] – 2025-10-27

Breaking Change: Scoped file routing

  • ISaveable<TState> now declares StorageScope Scope (Global or Slot), making pathing explicit and removing the need to toggle SaveManager.SaveSlotIndex just to “ignore” slots.
  • Scope remembered at registration: SaveManager records a filename scope mapping when RegisterSaveable(...) is called and uses it for path resolution. (Internal change; no new public API.)
  • FileHandler pathing updated: GetPartialPath() now prefixes slot{N}/ only for Slot‑scoped files. Attempting to save/load a Slot‑scoped file with no selected slot throws a clear error. (Prevents global files like Options from accidentally ending up in a slot folder.)

Migration notes

  • Add StorageScope Scope { get; } to every ISaveable<TState>. Use Global for shared data (e.g., options/settings) and Slot for per‑profile data.
  • Remove any code that temporarily sets SaveManager.SaveSlotIndex = -1 around global saves; it’s no longer necessary.

v0.13.0

23 Sep 02:59

Choose a tag to compare

[0.13.0] – 2025-09-22

Breaking Change

Whoa, 3 breaking changes in one day! ISaveable<TState>.FileVersion is now ISaveable<TState>.Version since that more accurately reflects that it is the "ISaveable" version and not the version of a file where the ISaveable is going - subtle but important difference.

Author's note: While this package has been used in production on shipped titles, changes and updates should still be considered volatile (in case that wasn't obvious from the 3 updates today).

Fixes

  • Fixed an issue where DoFileOperation would leave subsequent method calls on worker threads. This would cause loading to fail silently in some cases.

v0.12.0

23 Sep 01:25

Choose a tag to compare

[0.12.0] – 2025-09-22

Breaking Change: Versioning

Added versioning via ISaveable<TState>.FileVersion. On load, if the on-disk value doesn’t match the registered saveable’s FileVersion, that saveable is skipped and restored to defaults (others in the same file still load).

In the future, this version number might be used for data migrations (still considering this), but that functionality is not currently implemented.

Fixes

  • Fixed a regression where JSON Converters for Unity was not being utilized.

Migration notes

  • Just add int FileVersion { get; } to every ISaveable<TState>.

v0.11.0

22 Sep 18:41

Choose a tag to compare

[0.11.0] – 2025-09-22

Breaking Change

Moved from ISaveable to ISaveable<TState> to provide compile-time type safety, safer JSON deserialization (no type names), and clearer save/restore contracts. All saveables must now define a serializable TState and implement CaptureState(): TState and RestoreState(TState state).

Serialization & Safety

  • JSON now deserializes directly to each saveable’s TState (no type names emitted), reducing polymorphic-deserialization risk.
  • Existing save files that match the new TState shape should continue to load; files that relied on polymorphic object states will need a one-time migration.

Async/Awaitable & Concurrency

  • Replaced single-iteration “while not cancelled” wrappers with clear guard clauses.
  • Fixed a rare operation-queue race by making enqueue/start atomic behind a lock; IsBusy is reset in a finally block.
  • Broader cancellation: operations link destroyCancellationToken with Application.exitCancellationToken.
  • Exception surfacing: errors are logged and rethrown so callers can observe faults when awaiting.
  • Logging helpers include a Unity context only when on the main thread; background-thread logs remain safe.

Miscellaneous

  • FileHandler keeps the public API and formatting; small internal cleanups (consistent use of computed fullPath, clearer errors on delete).
  • Updated all Samples to the ISaveable<TState> pattern.

Migration notes

  1. Replace ISaveable with ISaveable<TState> and define a serializable TState (struct or class).
  2. Update methods to TState CaptureState() and void RestoreState(TState state).

v0.10.1

08 Aug 13:45

Choose a tag to compare

[0.10.1] - 2025-08-08

  • Background threads are now disabled by default. Exceptions are not always logged properly when using background threads, causing SaveManager methods to sometimes fail silently if bad data gets passed in (such as a NullReferenceException inside of an ISaveable.CaptureState() method). While background threads do increase performance, this should be considered an experimental feature until it's possible to properly catch exceptions while on a background thread.
  • Added try/catch blocks around SaveManager methods to ensure exceptions are logged for async methods.
  • Added more logging to SaveManager methods for better traceability.
  • Added the prefix [Save Async] to all log messages for easier identification in the console.

v0.10.0

06 Aug 22:57

Choose a tag to compare

[0.10.0] - 2025-08-06

Have you ever had a great idea, only to have a much (much) simpler version of that idea immediately after making a new release of your open source project?

This reverts several of the changes made in the release 0.9.0, simplifying the SaveManager API and achieving save slots with a simpler approach.

  • Previous changes to SaveManager methods - Save(), Load(), Erase(), and Delete() - that required a save slot parameter have been reverted. The FileHandler will now use the SaveManager.SaveSlotIndex in the GetPartialPath() method and use a save slot if the value is greater than -1.
  • SaveManager now stores a static int representing the current save slot, called SaveManager.SaveSlotIndex. Setting this to a value will use the save slot on that index, while -1 will ignore save slots.
  • Registering a Saveable that has already been registered will now only emit a warning rather than an error.

v0.9.0

06 Aug 20:41

Choose a tag to compare

[0.9.0] - 2025-08-06

  • Breaking Change: Added support for save slots! The SaveManager now requires a save slot parameter for all methods that interact with save data. This allows for multiple save files to be managed simultaneously, such as for different runs or user profiles.
  • Breaking Change: LoadDefaults() is a new method that replaces the previous Load() method signature that would allow for a boolean to ignore save data.
  • Erase() and Delete() methods no longer have a restoreDefaultSaveState parameter. Instead, it is recommended to use LoadDefaults() to restore the default state of ISaveables after calling Erase() or Delete().
  • Updated license dates in all files to reflect the current year.

v0.8.3

30 Jul 21:08

Choose a tag to compare

[0.8.3] - 2025-07-30

  • Added .meta files back for GitHub files since their absence was causing errors in Unity due to package folders being immutable.

v0.8.2

15 Jul 21:24

Choose a tag to compare

[0.8.2] - 2025-07-15

  • It's now possible to call Load() without loading actual data. When the bool ignoreSaveData is true, save files will be ignored and RestoreState() will be passed a null value. This can be useful when working in the Unity Editor or if you want RestoreState() to use default values.

v0.8.1

14 Jul 20:39

Choose a tag to compare

[0.8.1] - 2025-07-14

  • Fixed an issue where calling SaveManager.Load() multiple times with different filenames would result in ISaveables being restored to "null" by mistake.