Managing Large Save Files
How do professional games handle really large save files, like open world games with lots of player progress?
Professional games use several strategies to handle large amounts of save data efficiently:
Incremental Saving
Instead of saving everything at once, games often save different components independently:
#include <chrono>
using namespace std::chrono;
class SaveManager {
steady_clock::time_point LastInventorySave;
steady_clock::time_point LastQuestSave;
public:
void Update() {
auto Now = steady_clock::now();
// Save inventory every 5 minutes
if (Now - LastInventorySave > minutes(5)) {
SaveInventory();
LastInventorySave = Now;
}
// Save quests every 10 minutes
if (Now - LastQuestSave > minutes(10)) {
SaveQuests();
LastQuestSave = Now;
}
}
void SaveInventory() {
// Only save items that changed since last save
for (const auto& Item : PlayerInventory) {
if (Item.HasChanged) {
WriteItemToFile(Item);
}
}
}
};
Chunked World Data
Open world games typically divide the world into chunks and only save active areas:
struct WorldChunk {
static constexpr int SIZE = 64;
std::array<std::array<Tile, SIZE>, SIZE>
Tiles;
bool IsModified{false};
};
class World {
std::vector<std::vector<WorldChunk>> Chunks;
void SaveActiveChunks() {
const int PlayerChunkX = PlayerPos.X /
WorldChunk::SIZE;
const int PlayerChunkY = PlayerPos.Y /
WorldChunk::SIZE;
// Save chunks near player
for (int dx = -1; dx <= 1; ++dx) {
for (int dy = -1; dy <= 1; ++dy) {
SaveChunkIfModified(PlayerChunkX + dx,
PlayerChunkY + dy);
}
}
}
};
Compression
Large save files are typically compressed before writing to disk:
#include <zlib.h>
#include <vector>
std::vector<char> CompressSaveData(
const std::vector<char>& Data) {
std::vector<char> CompressedData;
z_stream Stream{};
// Initialize zlib
deflateInit(&Stream, Z_BEST_COMPRESSION);
// Compress data in chunks
const int CHUNK_SIZE = 16384;
char OutBuffer[CHUNK_SIZE];
// Compression code here...
deflateEnd(&Stream);
return CompressedData;
}
Reference Data
Instead of saving full copies of common objects, save references to shared data:
struct Item {
int TemplateId; // Reference to item template
int Count; // Instance-specific data
// Don't save template data like name, description, icon...
};
This combination of techniques allows games to manage massive amounts of save data while maintaining reasonable file sizes and save/load times.
Working with Data
Learn techniques for managing game data, including save systems, configuration, and networked multiplayer.