You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Moved from ISaveable to ISaveable<TState> to provide compile-time type safety, safer JSON deserialization (no type names), and clearer save/restore contracts.
Copy file name to clipboardExpand all lines: CHANGELOG.md
+29Lines changed: 29 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,5 +1,34 @@
1
1
# Changelog
2
2
3
+
## [0.11.0] – 2025-09-22
4
+
5
+
### Breaking Change
6
+
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)`.
7
+
8
+
### Serialization & Safety
9
+
10
+
- JSON now deserializes directly to each saveable’s `TState` (no type names emitted), reducing polymorphic-deserialization risk.
11
+
- 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.
12
+
13
+
### Async/Awaitable & Concurrency
14
+
15
+
- Replaced single-iteration “while not cancelled” wrappers with clear guard clauses.
16
+
- Fixed a rare operation-queue race by making enqueue/start atomic behind a lock; `IsBusy` is reset in a `finally` block.
17
+
- Broader cancellation: operations link `destroyCancellationToken` with `Application.exitCancellationToken`.
18
+
- Exception surfacing: errors are logged and rethrown so callers can observe faults when awaiting.
19
+
- Logging helpers include a Unity context only when on the main thread; background-thread logs remain safe.
20
+
21
+
### Miscellaneous
22
+
23
+
-`FileHandler` keeps the public API and formatting; small internal cleanups (consistent use of computed `fullPath`, clearer errors on delete).
24
+
- Updated all Samples to the `ISaveable<TState>` pattern.
25
+
26
+
### Migration notes
27
+
28
+
1. Replace ISaveable with `ISaveable<TState>` and define a serializable `TState` (struct or class).
29
+
2. Update methods to `TState CaptureState()` and `void RestoreState(TState state)`.
30
+
31
+
3
32
## [0.10.1] - 2025-08-08
4
33
- 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.
5
34
- Added try/catch blocks around SaveManager methods to ensure exceptions are logged for async methods.
// If the file does not exist, return an empty string and log a warning.
153
-
if(!Exists(pathOrFilename))
154
-
{
155
-
Debug.LogWarning($"[Save Async] FileHandler.ReadFile() - File does not exist at path \"{fullPath}\". This may be expected if the file has not been created yet.");
// If the file is empty, return an empty string and log a warning.
162
-
if(string.IsNullOrEmpty(fileContent))
163
-
{
164
-
if(SaveManager.SaveSlotIndex>-1)
165
-
Debug.LogWarning($"[Save Async] FileHandler.ReadFile() - The file \"{pathOrFilename}\" in slot index {SaveManager.SaveSlotIndex} was empty. This may be expected if the file has been erased.");
166
-
else
167
-
Debug.LogWarning($"[Save Async] FileHandler.ReadFile() - The file \"{pathOrFilename}\" was empty. This may be expected if the file has been erased.");
168
-
169
-
returnstring.Empty;
170
-
}
171
-
172
-
returnfileContent;
173
-
}
174
-
catch(UnauthorizedAccessExceptionex)
144
+
stringfullPath=GetFullPath(pathOrFilename);
145
+
146
+
if(!File.Exists(fullPath))
175
147
{
176
-
Debug.LogError($"[Save Async] FileHandler.ReadFile() - Access denied to file \"{pathOrFilename}\": {ex.Message}");
148
+
Debug.LogWarning($"[Save Async] FileHandler.ReadFile() - File does not exist at path \"{fullPath}\". This may be expected if the file has not been created yet.");
Debug.LogWarning($"[Save Async] FileHandler.ReadFile() - The file \"{pathOrFilename}\" in slot index {SaveManager.SaveSlotIndex} was empty. This may be expected if the file has been erased.");
158
+
else
159
+
Debug.LogWarning($"[Save Async] FileHandler.ReadFile() - The file \"{pathOrFilename}\" was empty. This may be expected if the file has been erased.");
160
+
182
161
returnstring.Empty;
183
162
}
163
+
164
+
returnfileContent;
184
165
}
185
-
166
+
186
167
/// <summary>
187
168
/// Returns the contents of a file at the given path or filename.
0 commit comments