Model factories and settings

How model creation works

FPulseSaveModelFactoryRegister::CreatePulseSaveModel resolves models in this order:

  1. UPulseSaveInterface::GetSaveModelClass override from the target object
  2. Registered factories (RegisterModelFactory, reverse registration order)
  3. Default blueprint factory (DefaultModelFactory)
  4. Default script factory (SetDefaultScriptFactory)
  5. UPulseSaveSettings::DefaultModelClass

UPulseSaveManager::GetOrCreateModelForObject uses this to create the model, then calls InitializeNewModel(). If a model already exists for the object’s identifier (cached from a previous save or load), the cached model is rebound to the current object and reused instead. The main load process and LoadSingleObject also reuse this identifier cache when resolving models from records. Static models are not part of this cache: they have their own records and identifiers (see Models and collectors). Cached object models are included in every main Save() process even when no collector returns them. See ResetCachedSaveModels() to clear the object-model cache. The manager keeps cached object-models alive across garbage collection until that reset is requested.

Built-in factory

At module startup (FPulseSaveModule::StartupModule), Pulse Save registers:

ModelFactoryRegister.RegisterModelFactory(MakeShared<FPulseSaveModelFactory_Actor>());

This maps AActor objects to UPulseSaveActorModel.

C++ custom factories

Use the provided macros:

DECLARE_SAVE_MODEL_FACTORY_EXTERN(MyFactory, MYMODULE_API)
DEFINE_SAVE_MODEL_FACTORY(MyFactory, AMySaveableActor, UMyActorSaveModel)

Then register:

IPulseSave::Get().GetModelFactoryRegister().RegisterModelFactory(MakeShared<FPulseSaveModelFactory_MyFactory>());

Blueprint model factory

Blueprint factories derive from UBP_PulseSaveModelFactory and implement:

UPulseSaveModel* CreatePulseSaveModel(UPulseSaveManager* SaveManger, UObject* ObjectToSave);

Return nullptr when a factory does not handle an object.

Plugin settings

Project settings section is registered as:

  1. Project > Pulse > Save

Relevant settings classes:

  1. UPulseSaveSettings — public, general settings.
  2. UPulseSaveSettingsPrivate — extends UPulseSaveSettings with factory-registration-only settings (kept separate since these are read once at module startup, not meant for runtime use).

Available configuration fields:

  1. DefaultModelClass (UPulseSaveSettings) — used as the last resort when no factory resolves a model for an object (a check() requires this to always resolve to something valid).
  2. DefaultProcessTimeout (UPulseSaveSettings) — default per-model save/load timeout in seconds (default 60.0, -1 disables it). Overridable per model via UPulseSaveModel::GetTimeoutOverride.
  3. DefaultModelFactory (UPulseSaveSettingsPrivate) — preferred blueprint factory, tried before the script default factory.
  4. SaveModelFactories (UPulseSaveSettingsPrivate) — additional blueprint factories registered at startup.
  5. MigrationFallback (UPulseSaveSettings) — what happens if a record does not match its model and no migration is registered (Fail, ReinterpretByProperty, KeepOldModel; default Fail).
  6. Migrations (UPulseSaveSettingsPrivate) — UPulseSaveModelMigration classes registered at startup.
  7. ClassRedirects (UPulseSaveSettingsPrivate) — old model class path to new model class.
  8. EditorReportMode / PackagedReportMode (UPulseSaveSettings) — when reports are written in the editor and in a packaged game (Disabled, OnFailure, Always; defaults Always and OnFailure).
  9. MaxStoredReports (UPulseSaveSettings) — how many report files are kept (default 50).

  10. bEnableGlobalManagerPool (UPulseSaveSettings) — whether the game instance subsystem with the global save manager pool is created (default false, restart required). See Save manager workflow.

See Reports for 8 and 9.

See Save migration for 5 to 7.

Resolving the model class

FPulseSaveModelFactoryRegister::ResolveModelClass follows the same order as CreatePulseSaveModel but only returns the class. It is used when loading to check if a record was saved with the model class an object uses now. IPulseSaveModelFactory::GetSaveModelClass(UObject*) lets a factory answer this without creating a model; DEFINE_SAVE_MODEL_FACTORY implements it.


This site uses Just the Docs, a documentation theme for Jekyll.