VDSaveSystem is a high-performance, modular save & load framework for Unreal Engine 5.5, architected around UGameInstanceSubsystem.
Designed for everything from small indie projects to large-scale AAA open-world titles (World Partition, Level Streaming, Data Layers), complex physics simulation, multiplayer, encryption, hardware-accelerated compression, and cloud backend integration (Steam Cloud, Epic Online Services, custom REST APIs).
- Architecture & Key Features
- Directory & Save File Structure
- Quick Start
- Subsystem: UVDSaveManagerSubsystem
- World Saving & Loading
- Slots, Rotation & AutoSaves
- Sidecar Metadata & Screenshots (Thumbnails)
- Custom Save Objects (VDCustomSaveGame)
- Global Player Profile (Player Profile)
- Multiplayer & Network Support
- World Partition, Level Streaming & Data Layers
- Destroyed Actor Tracking
- Save Guards & Blockers
- Compression, Encryption & Security
- Automated Backups & Storage Quotas
- Cloud Saves (Steam Cloud / Epic Online Services)
- Screen Transitions (Camera Fade Overlay)
- Asset & Class Redirectors
- Developer Console Commands
- Automation Unit Tests
- Project Settings Reference
- C++ & Blueprint Integration Examples
- Subsystem-First Architecture (
UGameInstanceSubsystem):- Instantiated automatically with
UGameInstanceand globally accessible from any C++ or Blueprint scope. - Zero requirement to place manager actors (
SaveManagerActor) on levels. - Keeps persistent memory alive across seamless map travel and level transitions.
- Instantiated automatically with
- Sidecar Slot File Structure:
- Each slot is stored in its own isolated subfolder.
- Slot metadata is duplicated into a lightweight JSON sidecar file (
Metadata.json). - Loading screens and UI menus can parse 50+ save slots in 1–2 milliseconds without decompressing multi-megabyte binary dumps.
- World Partition & Data Layer Compatibility:
- Automatically captures and restores active Data Layer runtime states (
EDataLayerRuntimeState::Activated). - Seamlessly handles actor state caching when streaming levels/cells unload.
- Automatically captures and restores active Data Layer runtime states (
- Deep Component & Attachment Hierarchy Serialization:
- Captures dynamic runtime-spawned components (
Runtime Components). - Preserves nested attached actors (
Attached Actors), socket names, and relative transforms.
- Captures dynamic runtime-spawned components (
- Physics & Velocity Preservation:
- Stores linear and angular velocities (
LinearVelocity,AngularVelocity) for physics-simulating primitives and characters withCharacterMovementComponent.
- Stores linear and angular velocities (
- Fault Tolerance & Reliability:
- Automatic timestamped backups prior to slot overwrite.
- Header integrity validation with unique magic bytes (
VD_SAVE_MAGIC = 0x56445356). - Automatic disk storage quota enforcement and backup pruning.
All save files are stored in [ProjectDirectory]/Saved/VDSaves/ by default:
Saved/
└── VDSaves/
├── Slot_1/
│ ├── SaveData.vdsave <-- Binary world payload (Oodle compressed + AES-256 encrypted)
│ ├── SaveData_Backup_*.vdsave <-- Automatic backup files
│ ├── Metadata.json <-- Lightweight JSON metadata for instant UI queries
│ └── Thumbnail.jpg <-- Slot screenshot (256x256)
├── AutoSave_1/
│ ├── SaveData.vdsave
│ ├── Metadata.json
│ └── Thumbnail.jpg
├── QuickSave_1/
│ ├── SaveData.vdsave
│ ├── Metadata.json
│ └── Thumbnail.jpg
├── CustomGlobals/ <-- Global custom save objects
│ └── InventorySave.vdsave
└── GlobalProfile.vdprof <-- Global player settings profile (audio, video, input)
To ensure a property on an Actor or Component is serialized by the save system, mark it with the SaveGame specifier.
UPROPERTY(EditAnywhere, BlueprintReadWrite, SaveGame, Category = "Stats")
int32 Health = 100;
UPROPERTY(EditAnywhere, BlueprintReadWrite, SaveGame, Category = "Stats")
TArray<FString> InventoryItems;- Select the variable in the My Blueprint panel.
- In the Details panel, expand the advanced options.
- Check the Save Game checkbox.
Any AActor, UActorComponent, or UObject implementing UVDSaveableInterface participates in the save/load pipeline.
| Method | Description | Default Implementation |
|---|---|---|
OnBeforeSave() |
Called immediately before the object is serialized into the byte buffer. Use this to prepare data. | Empty |
OnAfterLoad() |
Called immediately after the object has been deserialized. Use this to update UI, visuals, materials, animations. | Empty |
ShouldSaveTransform() |
Determines whether the Actor's world transform (location, rotation, scale) should be saved and restored. | true |
GetSaveableSubobjects(OutObjects) |
Allows passing child UObject* instances (e.g. inventory objects, quest trackers) that should also be serialized. |
Empty Array |
// MyChestActor.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "VDSaveableInterface.h"
#include "MyChestActor.generated.h"
UCLASS()
class MYGAME_API AMyChestActor : public AActor, public IVDSaveableInterface
{
GENERATED_BODY()
public:
UPROPERTY(SaveGame)
bool bIsOpen = false;
UPROPERTY(SaveGame)
TArray<FString> StoredLoot;
// IVDSaveableInterface
virtual void OnBeforeSave_Implementation() override;
virtual void OnAfterLoad_Implementation() override;
virtual bool ShouldSaveTransform_Implementation() override { return false; } // Static chest
};
// MyChestActor.cpp
#include "MyChestActor.h"
void AMyChestActor::OnBeforeSave_Implementation()
{
// Prepare data prior to serialization
}
void AMyChestActor::OnAfterLoad_Implementation()
{
// Apply loaded state to visual representation
if (bIsOpen)
{
// Snap chest lid open without replaying opening animation
}
}For dynamically spawned actors (SpawnActor) or actors placed in World Partition levels, attach the UVDSaveIdentityComponent.
- Automatically generates a stable unique GUID (
FGuid StableId). - During save/load, the system first matches actors by their
StableId. If not found, it falls back toFName. - If an actor was spawned during gameplay and does not exist on level load, the system automatically respawns it using the recorded class path (
ActorClassPath) and applies the serialized payload.
// Adding in C++ constructor
MyIdentityComp = CreateDefaultSubobject<UVDSaveIdentityComponent>(TEXT("SaveIdentity"));Use the Get VDSaveManagerSubsystem node or any high-level functions under the VDSaveSystem category.
#include "VDSaveManagerSubsystem.h"
// From any UObject with a valid World Context (Actor, Widget, GameMode, etc.):
UVDSaveManagerSubsystem* SaveManager = GetGameInstance()->GetSubsystem<UVDSaveManagerSubsystem>();
if (SaveManager)
{
SaveManager->SaveGame(this, TEXT("Slot_1"));
}The subsystem provides Blueprint dynamic multicast delegates and native C++ multicast delegates:
| Blueprint Delegate | Native C++ Delegate | Signature | Description |
|---|---|---|---|
OnSaveCompleted |
OnSaveCompletedNative |
(bool bSuccess, const FString& SlotName) |
Fires after save data has been successfully written to disk. |
OnLoadCompleted |
OnLoadCompletedNative |
(bool bSuccess, const FString& SlotName) |
Fires after world data has been completely loaded and applied. |
OnAutoSaveTriggered |
— | (const FString& SlotName) |
Fires when an automatic save is initiated. |
OnProfileSaved |
— | (bool bSuccess) |
Fires after the global profile has been saved. |
OnProfileLoaded |
— | (bool bSuccess) |
Fires after the global profile has been loaded. |
void AMyGameMode::BeginPlay()
{
Super::BeginPlay();
if (UVDSaveManagerSubsystem* SaveMgr = GetGameInstance()->GetSubsystem<UVDSaveManagerSubsystem>())
{
SaveMgr->OnSaveCompletedNative.AddUObject(this, &AMyGameMode::HandleSaveCompleted);
SaveMgr->OnLoadCompletedNative.AddUObject(this, &AMyGameMode::HandleLoadCompleted);
}
}
void AMyGameMode::HandleSaveCompleted(bool bSuccess, const FString& SlotName)
{
UE_LOG(LogTemp, Log, TEXT("Slot %s save finished with status: %s"), *SlotName, bSuccess ? TEXT("Success") : TEXT("Failure"));
}The framework provides multiple execution models to suit any game flow:
- Background ThreadPool Execution:
- Object state snapshotting takes place on the GameThread, while binary serialization, Oodle compression, AES encryption, and file I/O execute asynchronously in
EAsyncExecution::ThreadPool. Zero frame drops or game hitches.
- Object state snapshotting takes place on the GameThread, while binary serialization, Oodle compression, AES encryption, and file I/O execute asynchronously in
- Blueprint Async Action Nodes:
AsyncSaveGame— Saves the specified slot withOnSuccessandOnFailureexecution pins.AsyncLoadGame— Loads the specified slot withOnSuccessandOnFailureexecution pins.AsyncAutoLoadGame— Finds the latest save slot by timestamp and loads it asynchronously.
- Latent Nodes:
SaveGameActorsAsync,LoadGameActorsAsyncwithOnCompletedandOnFailedexecution branches.
The bitmask enum EVDSaveDataFilter enables precise control over which segments of the world are captured or restored:
UENUM(BlueprintType, meta = (Bitflags, UseEnumValuesAsMaskValuesInEditor = "true"))
enum class EVDSaveDataFilter : uint8
{
None = 0,
Player = 1 << 0, // Pawn, PlayerController, PlayerState
LevelActors = 1 << 1, // All level actors implementing IVDSaveableInterface
GameState = 1 << 2, // GameState
All = 0xFF // Complete snapshot of the game world
};Use case: To reload only the player character at a checkpoint while leaving environmental destruction intact, supply EVDSaveDataFilter::Player.
The LoadGameAndMap(WorldContextObject, SlotName) function performs an automated two-stage transition:
- Reads slot metadata to identify the saved level (
MapName). - If the current world map differs from the saved map, it loads the destination map via
UGameplayStatics::OpenLevel. - Once map loading completes, it automatically restores the world state.
For expansive levels containing thousands of actors, restoring every object in a single frame can cause noticeable hitching.
The plugin provides a Deferred Loading mode:
LevelLoadMethod=DeferredLoadBatchSize=30(number of level actors restored per frame).
The subsystem registers an FTSTicker delegate to distribute actor deserialization smoothly across multiple frames without dropping below target frame rates.
SaveGameAuto(WorldContextObject)— Saves into rotating slots:AutoSave_1,AutoSave_2, ...,AutoSave_N.SaveGameQuick(WorldContextObject)— Saves into rotating slots:QuickSave_1, ...,QuickSave_N.
- Checks for unused slots numbered from
1toMaxAutosaveSlots. - If an unused candidate is available, that slot is used.
- If all slots are occupied, the subsystem selects and overwrites the oldest slot based on UTC timestamp.
The framework features an automated timer-based save loop:
StartPeriodicAutoSave(IntervalSeconds)— Starts the periodic autosave timer (default: 300 seconds).StopPeriodicAutoSave()— Clears and stops the timer.IsPeriodicAutoSaveActive()— Checks whether the autosave timer is currently running.
GetAllSaveSlots()— ReturnsTArray<FVDSaveMetadata>sorted by timestamp descending (newest saves first).GetLatestSaveSlotName()— Returns the identifier of the most recent save slot.DeleteSaveSlot(SlotName)— Deletes the slot directory and all associated files (SaveData.vdsave,Metadata.json,Thumbnail.jpg, backups).GetCurrentSaveSlot()/SetCurrentSaveSlot(SlotName)— Gets or sets the active slot name.
USTRUCT(BlueprintType)
struct FVDSaveMetadata
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadWrite)
FString SlotName; // Save slot name
UPROPERTY(EditAnywhere, BlueprintReadWrite)
FDateTime Timestamp; // Creation date/time in UTC
UPROPERTY(EditAnywhere, BlueprintReadWrite)
FString MapName; // Name of the saved level/map
UPROPERTY(EditAnywhere, BlueprintReadWrite)
int32 SaveVersion; // Version code of save schema
UPROPERTY(EditAnywhere, BlueprintReadWrite)
float PlaytimeSeconds; // Cumulative session playtime in seconds
UPROPERTY(EditAnywhere, BlueprintReadWrite)
FString ScreenshotPath; // Relative path to slot thumbnail
UPROPERTY(EditAnywhere, BlueprintReadWrite)
TMap<FString, FString> CustomData; // Custom key-value string pairs
UPROPERTY(EditAnywhere, BlueprintReadWrite)
FString CharacterName; // Player character name
UPROPERTY(EditAnywhere, BlueprintReadWrite)
int32 PlayerLevel; // Player character level
UPROPERTY(EditAnywhere, BlueprintReadWrite)
FString CurrentQuest; // Active quest title
};Building a "Load Game" menu requires only a single call:
TArray<FVDSaveMetadata> AllSlots = SaveSubsystem->GetAllSaveSlots();The subsystem reads only the small Metadata.json files. This operation completes in fractions of a millisecond even on mobile devices and consoles.
Before invoking SaveGame, enrich the metadata for UI presentation:
SaveSubsystem->SetMetadataPlayerInfo(TEXT("Geralt"), 42, TEXT("The Witcher's Calling"));
SaveSubsystem->SetMetadataCustomData(TEXT("Difficulty"), TEXT("DeathMarch"));
SaveSubsystem->SetMetadataCustomData(TEXT("LocationTitle"), TEXT("Novigrad"));To prevent frame drops when scrolling through save slots with image previews:
- Blueprint: The
Load Slot Thumbnail Asyncnode loads the screenshot in the background and returns aUTexture2D*. - C++:
UVDSaveManagerSubsystem::LoadSaveThumbnail(ScreenshotPath).
For modular persistence subsystems (e.g. global achievements, talent trees, inventory records, merchant states), the framework provides UVDCustomSaveGame (analogous to EMSCustomSaveGame).
- Derive a new class from
UVDCustomSaveGamein C++ or Blueprint (e.g.UInventorySaveGame). - Add variables tagged with the
SaveGameflag. - Configure the default class properties:
SaveFileName— Target file name (e.g.InventoryData).bUseSaveSlot— Iftrue, saves inside the active slot folder; iffalse, saves globally underSaved/VDSaves/CustomGlobals/.
// InventorySaveGame.h
#pragma once
#include "VDCustomSaveGame.h"
#include "InventorySaveGame.generated.h"
UCLASS()
class MYGAME_API UInventorySaveGame : public UVDCustomSaveGame
{
GENERATED_BODY()
public:
UInventorySaveGame()
{
SaveFileName = TEXT("InventoryData");
bUseSaveSlot = true; // Bound to active slot
}
UPROPERTY(SaveGame, BlueprintReadWrite)
TArray<FString> ItemIds;
UPROPERTY(SaveGame, BlueprintReadWrite)
int32 Gold = 500;
};// 1. Retrieve or load instance (cached in memory)
UInventorySaveGame* InvSave = Cast<UInventorySaveGame>(SaveSubsystem->GetCustomSaveObject(UInventorySaveGame::StaticClass(), CurrentSlot));
// 2. Modify properties
InvSave->Gold += 100;
// 3. Commit to disk
SaveSubsystem->SaveCustomObject(InvSave, CurrentSlot);
// 4. Check existence on disk
bool bExists = SaveSubsystem->DoesCustomSaveExist(UInventorySaveGame::StaticClass(), CurrentSlot);
// 5. Delete from disk
SaveSubsystem->DeleteCustomSaveObject(UInventorySaveGame::StaticClass(), CurrentSlot);
// 6. Save all open custom objects at once
SaveSubsystem->SaveAllCustomObjects();To persist arbitrary arrays of UObject* instances without creating dedicated classes:
SaveObjectCollection(Objects, SaveSlot, FileName)LoadObjectCollection(Objects, SaveSlot, FileName)
Using the FVDRawObjectSaveData structure:
FVDRawObjectSaveData Item;
Item.DataId = FName("QuestManager");
Item.Object = MyQuestManagerInstance;The global profile is stored in Saved/VDSaves/GlobalProfile.vdprof independently of gameplay save slots. Ideal for:
- Video, audio, graphics, and keybinding settings.
- Account-wide statistics, unlockables, and achievements.
// Store custom key-value pairs
SaveSubsystem->SetProfileCustomData(TEXT("Audio_MasterVolume"), TEXT("0.85"));
SaveSubsystem->SetProfileCustomData(TEXT("FOV"), TEXT("105"));
// Retrieve values
FString Vol = SaveSubsystem->GetProfileCustomData(TEXT("Audio_MasterVolume"));
// Serialize an entire custom UObject into the profile
SaveSubsystem->SaveProfile(MyUserSettingsObject);
SaveSubsystem->LoadProfile(MyUserSettingsObject);
// Check if a profile file exists on disk
bool bHasProfile = SaveSubsystem->DoesProfileSaveExist();- World state serialization (
Level Actors,Data Layers,GameState) must be executed exclusively on the server (HasSaveAuthority() == true— Dedicated Server, Listen Server, or Standalone). - If a client invokes
SaveGamewith theLevelActorsflag, the subsystem safely clamps the filter toEVDSaveDataFilter::Playeronly.
In multiplayer sessions, connected players are identified by their unique network identifier FUniqueNetIdRepl (SteamID, EOS ProductUserId, etc.).
// Save state for a specific connected PlayerController (Pawn + Controller + PlayerState)
SaveSubsystem->SavePlayerState(PlayerController, SlotName);
// Restore player state (e.g. inside GameMode::OnPostLogin)
SaveSubsystem->LoadPlayerState(PlayerController, SlotName);Dedicated standalone player file persistence:
SaveCustomPlayer(Controller, UniquePlayerId, SaveSlot)LoadCustomPlayer(Controller, UniquePlayerId, SaveSlot)DeleteCustomPlayer(UniquePlayerId, SaveSlot)
When bSaveWorldPartitionDataLayers is enabled, the subsystem queries UDataLayerManager, records all active Data Layers, and restores their runtime state (EDataLayerRuntimeState::Activated) upon loading.
In games using Level Streaming or World Partition, actors are dynamically unloaded as the player moves across the world.
- With
bEnableStreamingAutoMemoryCacheenabled, the subsystem intercepts level unloads (HandleLevelRemovedFromWorld) and caches modified actors into an in-memory mapUnloadedLevelActorsCache. - When the player returns to that area (
HandleLevelAddedToWorld), actors are restored from memory. - During a full world save, memory-cached actors from unloaded cells are merged with active scene actors.
The bProtectPlayerPhysicsOnCellStream option briefly suspends character physics and gravity during initial cell streaming, preventing the pawn from falling through geometry before collision meshes are loaded.
When an actor on a level is permanently destroyed (e.g. collected key, broken bridge, defeated unique boss), its destruction must be recorded.
Use the destruction tracking helpers:
// 1. Mark actor as destroyed and immediately invoke Destroy()
SaveSubsystem->DestroyAndMarkSaveActor(KeyActor);
// 2. Or register destruction manually before calling standard Destroy()
SaveSubsystem->MarkActorAsDestroyed(KeyActor);
KeyActor->Destroy();Upon subsequent loads, the subsystem matches recorded actors by StableId or FName and removes them prior to game initialization.
To prevent saves during sensitive gameplay sequences (cinematic cutscenes, dialogues, execution animations, boss encounters), use the reason-based guard system:
// Block saving with a named reason
SaveSubsystem->AddSaveBlockReason(FName("Cutscene_Intro"));
SaveSubsystem->AddSaveBlockReason(FName("BossFight"));
// Query if saving is allowed
TArray<FName> ActiveReasons;
if (!SaveSubsystem->CanSaveGame(this, ActiveReasons))
{
// Saving is blocked! ActiveReasons contains the list of blockers
}
// Remove a specific blocker
SaveSubsystem->RemoveSaveBlockReason(this, FName("Cutscene_Intro"));
// Clear all active save blockers
SaveSubsystem->ClearAllSaveBlockReasons();- Oodle compression (standard in Unreal Engine 5) is enabled by default, reducing save file sizes on disk by 70–90%.
- Corrupted or truncated data streams are handled gracefully without application crashes.
To safeguard save files against client-side tampering:
- Set
bEnableSaveEncryption = truein Project Settings. - Click Generate New Key in the editor or provide a passphrase string.
- The passphrase is hashed via SHA-1 to produce a 256-bit AES cipher key for payload encryption.
bAutoBackupPreviousData— Prior to overwriting an existing slot, the previous file is copied toSaveData_Backup_[Timestamp].vdsave.MaxBackupFilesPerSlot— Maximum number of backup files retained per slot (oldest backups pruned automatically).MaxStorageQuotaMB— Global disk quota for the entireVDSaves/folder.EnforceStorageQuotaAndCleanupBackupsverifies total storage consumption and prunes historical backups when exceeding limits.
For synchronizing slots with Steam Cloud, Epic Online Services (EOS), or cloud backends, the subsystem packs the complete slot folder into a single byte archive:
// Export complete slot folder (SaveData.vdsave + Metadata.json + Thumbnail.jpg) to TArray<uint8>
TArray<uint8> CloudArchiveBytes;
if (SaveSubsystem->ExportSlotAsSingleArchiveBuffer(TEXT("Slot_1"), CloudArchiveBytes))
{
// Send CloudArchiveBytes to Steam Remote Storage / EOS / Cloud REST API
}
// Import from byte buffer back onto local disk
TArray<uint8> DownloadedBytes = /* received from cloud */;
SaveSubsystem->ImportSlotFromSingleArchiveBuffer(TEXT("Slot_1"), DownloadedBytes);ExportCloudData(SlotName, FileType, OutBytes, CustomFileName)ImportCloudData(SlotName, FileType, InBytes, CustomFileName)- Supported
EVDCloudFileType:CompleteSlot,CustomSave,CustomPlayer.
- Supported
To conceal level streaming and actor repositioning hitches during loads, the plugin includes a native Slate overlay widget SVDFadeOverlay:
- In Project Settings:
bEnableCameraFadeOnLoad=trueCameraFadeDuration=0.5seconds.CameraFadeColor=FLinearColor::Black
- When loading begins, the viewport fades to black and smoothly fades back in once all level actors have been initialized.
When renaming Blueprint classes or reorganizing folder structures during game development, legacy saves remain compatible:
RuntimeActorRedirects—TMap<FSoftClassPath, FSoftClassPath>for remapping moved actor classes.LevelRedirects—TMap<FSoftObjectPath, FSoftObjectPath>for remapping renamed map assets.
Access these commands in the developer console (~):
| Command | Example | Description |
|---|---|---|
vd.save [SlotName] |
vd.save Slot_Debug |
Saves the world to the specified slot (defaults to ManualSave_Console). |
vd.load [SlotName] |
vd.load Slot_Debug |
Loads the specified slot. If omitted, loads the latest save slot. |
vd.list |
vd.list |
Outputs a formatted table of all save slots (playtime, map, level, timestamp). |
vd.wipe |
vd.wipe |
Warning: Recursively deletes the entire Saved/VDSaves/ folder. |
The plugin includes 5 automated tests accessible via Tools -> Session Frontend -> Automation:
VDSaveSystem.Crypto.AES256— Validates encryption and decryption integrity with correct and invalid keys.VDSaveSystem.Compression.OodleVsZlib— Validates Oodle compression and decompression ratios.VDSaveSystem.Serialization.PhysicsAndTransforms— Tests physics velocity, transform, and component serialization.VDSaveSystem.Storage.QuotaAndBackups— Tests disk quota enforcement and automated backup pruning.VDSaveSystem.Cloud.ArchivePackingAndUnpacking— Validates single-archive packing and unpacking for cloud saves.
Located under: Project Settings -> Game -> VD Save System.
| Property | Type | Default | Description |
|---|---|---|---|
bEnableSaveEncryption |
bool |
false |
Enable symmetric AES-256 encryption for save payloads. |
SaveEncryptionKey |
FString |
"" |
Passphrase string hashed into a 256-bit encryption key. |
| Property | Type | Default | Description |
|---|---|---|---|
SaveDirectoryName |
FString |
"VDSaves" |
Subfolder inside Saved/ for storing save data. |
ProfileSaveFileName |
FString |
"GlobalProfile.vdprof" |
File name for the global player profile. |
bUseCompression |
bool |
true |
Enable Oodle / Zlib compression. |
bAutoBackupPreviousData |
bool |
true |
Automatically back up slot files before overwriting. |
MaxBackupFilesPerSlot |
int32 |
2 |
Maximum backup copies per slot (0 = unlimited). |
MaxStorageQuotaMB |
int32 |
0 |
Disk quota limit in megabytes (0 = unlimited). |
| Property | Type | Default | Description |
|---|---|---|---|
LevelLoadMethod |
EVDLoadMethod |
Immediate |
Deserialization mode: Immediate (single frame) or Deferred (time-sliced). |
LoadBatchSize |
int32 |
30 |
Number of actors restored per frame in deferred mode. |
| Property | Type | Default | Description |
|---|---|---|---|
bEnableStreamingAutoMemoryCache |
bool |
true |
Cache modified actor states in memory when levels/cells unload. |
bSaveWorldPartitionDataLayers |
bool |
true |
Automatically capture and restore active Data Layer states. |
bProtectPlayerPhysicsOnCellStream |
bool |
true |
Suspend character gravity briefly during cell streaming. |
| Property | Type | Default | Description |
|---|---|---|---|
MaxAutosaveSlots |
int32 |
5 |
Maximum number of rotating autosave slots (AutoSave_1..N). |
MaxQuicksaveSlots |
int32 |
3 |
Maximum number of rotating quicksave slots (QuickSave_1..N). |
bEnablePeriodicAutoSave |
bool |
false |
Enable periodic timer-based autosaving at game start. |
AutoSaveIntervalSeconds |
float |
300.0 |
Interval between periodic autosaves in seconds. |
| Property | Type | Default | Description |
|---|---|---|---|
bAutoCaptureScreenshot |
bool |
true |
Capture a scene thumbnail when saving a slot. |
ScreenshotResolution |
FIntPoint |
(256, 256) |
Thumbnail resolution. |
ScreenshotFormat |
EVDSaveScreenshotFormat |
JPG |
Thumbnail image format (JPG, PNG, EXR). |
CompressionQuality |
int32 |
85 |
JPEG compression quality (1-100). |
bEnableCameraFadeOnLoad |
bool |
true |
Show full-screen camera fade overlay during world loading. |
CameraFadeDuration |
float |
0.5 |
Fade in/out duration in seconds. |
CameraFadeColor |
FLinearColor |
Black |
Solid color for loading overlay. |
// Inside your APlayerController or ACharacter:
void AMyPlayerController::SetupInputComponent()
{
Super::SetupInputComponent();
InputComponent->BindAction("QuickSave", IE_Pressed, this, &AMyPlayerController::OnQuickSavePressed);
InputComponent->BindAction("QuickLoad", IE_Pressed, this, &AMyPlayerController::OnQuickLoadPressed);
}
void AMyPlayerController::OnQuickSavePressed()
{
if (UVDSaveManagerSubsystem* SaveMgr = GetGameInstance()->GetSubsystem<UVDSaveManagerSubsystem>())
{
SaveMgr->SaveGameQuick(this);
}
}
void AMyPlayerController::OnQuickLoadPressed()
{
if (UVDSaveManagerSubsystem* SaveMgr = GetGameInstance()->GetSubsystem<UVDSaveManagerSubsystem>())
{
SaveMgr->AutoLoadGame(this); // Loads the most recent QuickSave or AutoSave
}
}[Event Construct]
│
▼
[Get VDSaveManagerSubsystem] ──► [Get All Save Slots] ──► [ForEachLoop]
│
┌────────────────────────────┘
▼
[Create Widget: WBP_SaveSlotEntry]
│
├─► Set SlotName (Array Element -> SlotName)
├─► Set PlaytimeText (Array Element -> PlaytimeSeconds)
├─► Set MapNameText (Array Element -> MapName)
├─► Set TimestampText (Array Element -> Timestamp)
│
├─► [Load Slot Thumbnail Async (SlotName)]
│ │
│ ▼
│ [Set Brush from Texture (Image_Preview)]
│
▼
[ScrollBox_Slots -> Add Child]
// Character with custom subobject quest log and talent tree:
void AMyCharacter::GetSaveableSubobjects_Implementation(TArray<UObject*>& OutObjects)
{
if (QuestLogInstance)
{
OutObjects.Add(QuestLogInstance);
}
if (SkillTreeInstance)
{
OutObjects.Add(SkillTreeInstance);
}
}This plugin is a commercial product distributed exclusively on Fab (Epic Games).
- License: By purchasing this plugin on Fab, you are granted a standard Epic Games Content License to use the product in an unlimited number of commercial and non-commercial projects (games, interactive apps, simulations, cinematic productions).
- Full Source Code Included: The plugin includes complete C++ source code and full Blueprint integration. You are free to modify, extend, and tailor the source code to the specific architectural requirements of your project.
- Distribution Restrictions: Direct resale, sublicensing, sharing, or public hosting of the plugin's source code or assets (including public GitHub/GitLab repositories) is strictly prohibited. The plugin may only be distributed as part of packaged, compiled final products (executable game builds).
- Updates & Engine Support: Your purchase on Fab includes lifetime access to all future updates, enhancements, bug fixes, and compatibility releases for future versions of Unreal Engine (UE 5.5, 5.6, 5.7, 5.8+).
Built with passion for Unreal Engine game developers.