Migration
Behavior changes (no action needed)
- Slot metas name the save they were written with.
FPulseSaveSlotMetahas a new fieldEntry(FPulseSaveEntryStamp, read only in Blueprint):WriteEntryWithMeta(and Save To Slot With Meta) stamps the meta with the bytes of the entry;WriteSlotMetakeeps the stamp of the meta it replaces while that entry is unchanged, else it writes the meta without one. Metas of earlier builds load with an empty stamp and are read as before; earlier builds skip the field.LoadFromSlotnow fillsFPulseSaveCheckResult::Files(what it did with the entry’s files, one file stat per load); a save clears it. -
The default load menu handler brings the slot meta in step after every load (also a failed one), with the new
Pulse::Save::SyncSlotMetaAfterLoad(Blueprint Sync Slot Meta After Load): when the load put the entry’s backup back, the meta backup goes back too if it was written with that data; a staged meta whose save is gone is dropped; the play time comes from the meta written with the loaded data, else from the meta the old rule picks. Blueprint handlers can call the node after Load From Slot (Async); without it nothing changes for them. - Pulse Check reports save ids made from names as warnings (Name based): objects saved as bytes without a Save Identity, ids that contain the name of an actor spawned while playing,
IPulseSaveInterfaceobjects whose identifier is the name-based key, and automatic components without a Save Identity (Fixed identifiers and Pulse Check). Nothing changes in saves; the warnings only point at ids that renames or another spawn order would break. - Save ids of automatic components are the same in packaged games as in the editor (with the PulseFoundation version that names automatic components
Pulse_<Class>_0in every build). Records of earlier packaged sessions were never found again and stay so. No data moves, so nothing has to be migrated.
From 1.x to 2.0
Pulse Save 2.0 records its reports with the report system of the free base plugin PulseFoundation (1.0 or newer) and drops its own report types, files and editor tab. The save API and the save format stay the same: saves of 1.x load unchanged.
Coming from 1.0
Pulse Save needs PulseFoundation since 1.1:
- Put PulseFoundation into the project (or engine) plugins next to Pulse Save. It is enabled together with Pulse Save.
- Rebuild the project.
- Only if a game module uses PulseFoundation types itself, or the linker reports unresolved PulseFoundation symbols (e.g. in a C++ subclass of
UPulseSaveManager): addPulseFoundationto the dependencies in that module’sBuild.cs.
Records stay until their object is destroyed
PrepareForSave() no longer removes the collected records whose object said IsPersistent false. Records stay until their object is destroyed for good: placed actors leave a tombstone that removes them again when the save loads, spawned ones lose their record. Objects that were only unloaded (streaming, offline players) keep their state. A load that finds no object for a record no longer fails that record; it stays in the save game.
If your game relied on non-persistent records being dropped (temporary objects with new identifiers every session), call RemoveRecord(Identifier) for them, or destroy their actors so the tracker removes their records.
Reports
| 1.x | 2.0 |
|---|---|
| Editor tab Pulse Save Reports | Reports page of Tools > Debug > Pulse Debugger (plugin Save). PulseSave.OpenReports opens it. |
Files in Saved/PulseSave/Reports | Files in Saved/Pulse/Reports/Save (PulseFoundation format). Old files are not read any more. |
Settings EditorReportMode, PackagedReportMode, MaxStoredReports | One setting ReportPolicy (EditorMode, PackagedMode, MaxStoredReports) |
EPulseSaveReportMode | EPulseReportMode (PulseFoundation, same values) |
FPulseSaveReport, FPulseSaveReportModelEntry | FPulseReport with one entry per model |
EPulseSaveReportScope, EPulseSaveReportResult | The report type (Save, Load, SingleObject.Load, …) and the entry severity |
EPulseSaveMessageSeverity | EPulseDebugSeverity (PulseFoundation) |
IPulseSave::OnReportWritten() | Pulse::Debug::OnReportSubmitted() (all plugins; check Report.Plugin == "Save") |
Pulse::Save::Report::* (PulseSaveReportStorage.h) | Pulse::Debug::Reports::* (EnumerateReportFiles("Save"), LoadReportFromFile, GetReportRoot) |
What to do:
- Set the report settings again under Project Settings > Pulse > Save > Report. The old keys
EditorReportMode,PackagedReportModeandMaxStoredReportsinDefaultGame.iniare ignored; remove them. The defaults stay the same (Alwaysin the editor,OnFailurein packaged builds, 50 files). - Replace uses of the removed types listed above.
OnProcessed()/OnProcessedWithReport()andFPulseSaveProcessReportare unchanged. - Shipping builds no longer record reports (PulseFoundation’s debug tools are compiled out of shipping). Use a development or test build to get report files from a packaged game.
Nothing to do for the rest:
- Model messages (
LogInfo,LogWarning,LogError), report context and report slot work as before. - Save and load processes now also finish in the editor outside of PIE (Editor Utility Blueprints, automation specs). Before 2.0 they never completed there.
- Save and load processes are events on the Timeline page of the Pulse Debugger.
- Every save manager is a snapshot provider (category
Save): its state shows on the Live page, in the gameplay debugger category Pulse and withPulseDebugDump Save(see Console). BuildChunkskeeps its signature. Since 2.0 a save runs synchronous models first and splits into two chunks when an asynchronous model capturesAtEnd(null models are skipped). The plan is the purePulse::Save::PlanChunks, which an override can call.SaveMetaGameDirect,SaveMetaBytesDirectand the Blueprint Save Slot Save Game / Save Slot Meta Game delete a staged meta (.staging/slot_meta.sav) after they wrote, so every reader sees the direct write; if that delete fails they return false with the new errorStagedDiscardFailed. Commit a meta you staged yourself (FlushEntry(FPulseSaveSlot::MetaEntryId)) before a direct write.