# Make your plugin's objects save

> Declare what an object of your plugin or game saves, and what it does right before a save and after a load, without including a Rolly Save header or adding...

Product: Rolly Save 1.0.0 | Sheet: guide | Updated: 2026-10-31 | HTML: https://rolly-docs.pages.dev/save/guides/save-from-other-plugins/

## Declare what saves

- Flag each property to save `SaveGame`. In a struct, the member and every struct property above it need the flag.
- An object your object owns (its outer is your object, or an object your object owns) saves with it when a `SaveGame` property points at it, and comes back with its class, name and `SaveGame` properties. An asset or a type saves by path.
- A property bag (`FInstancedPropertyBag`) in a `SaveGame` property saves whole: every value in it, struct members without the flag included.
- For state that is not a property, override `Serialize`: call `Super::Serialize` first, then write your values when `Ar.IsSaveGame()` is true. Actors and scene components save their `SaveGame` properties only; their `Serialize` overrides do not run for saves.
- Editor-only properties and data are left out, in the editor too, since a packaged game has none.

```cpp
UCLASS()
class UMyQuestLog : public UActorComponent
{
	GENERATED_BODY()

public:
	virtual void Serialize(FArchive& Ar) override
	{
		Super::Serialize(Ar); // first: a save that writes before it cannot be loaded, so it is refused
		if (Ar.IsSaveGame())
		{
			Ar << Seed;
		}
	}

	UPROPERTY(SaveGame)
	TArray<FName> Finished;

	int32 Seed = 0;
};
```

## Which objects save

- A game instance subsystem or a world subsystem of your plugin saves with every save of the game, with no setup, when it has `SaveGame` properties of its own or declares one of the three functions below. Rolly Save finds it by its class path, so after renaming the class add `+ClassRedirects` under `[CoreRedirects]` in `Config/DefaultEngine.ini`: a load then gives the saved values to the renamed class.
- The same holds for the game instance, the Game Mode, the Game State and the Level Blueprint of the game's map.
- Any other object saves once the game registers it under a name with Register Object for Saving, such as `URollySaveSubsystem::Get(this)->RegisterObject(QuestLog, TEXT("QuestLog"))`. Your plugin does not call it itself, since that would need Rolly Save.
- Only the server or a standalone game saves; clients save nothing of the game's state.
- A load sets the saved values of a world subsystem and of the map's objects once the map's actors are initialized, before Begin Play; a game instance subsystem lives through the map change and takes its values then too. An object registered under a name takes its values when it registers, so a component that the game registers in Begin Play gets them inside that call.
- An object takes its saved values only when its class is the saved class or a child of it. A record of an object that is not there, such as a subsystem of your plugin while the plugin is turned off, is written back by the next save, so turning the plugin on again finds its state.

## Run code before a save and after a load

Declare any of these functions by its exact name, with no parameters and no return value, as a `UFUNCTION` that is neither static nor a remote call. In a Blueprint, add a function or custom event of that name without inputs or outputs.

| Function | Runs | Use it to |
|---|---|---|
| `OnRollySavePreSave` | Right before the object is written: on the saved object first, then on each object it owns | Copy state kept outside `SaveGame` properties into them |
| `OnRollySaveSaved` | Once the save that holds the object is written: on the saved objects and the objects they own, in the order they were written; not after a failed save | Clear a "changed since the last save" flag, or show that the game was saved |
| `OnRollySaveLoaded` | Once every record of the load applied, so pointers to other saved objects are set: on the owned objects first, innermost first, then on the saved object. After a load of the game that opens its map, before Begin Play | Rebuild state derived from the loaded values, such as caches and visuals |

```cpp
UFUNCTION(BlueprintNativeEvent, Category = "MyPlugin|Save")
void OnRollySavePreSave();

UFUNCTION(BlueprintNativeEvent, Category = "MyPlugin|Save")
void OnRollySaveSaved();

UFUNCTION(BlueprintNativeEvent, Category = "MyPlugin|Save")
void OnRollySaveLoaded();
```

All three run on the game thread. `OnRollySaveLoaded` does not run for an object whose saved values were refused or did not read to their end. A function of one of these names with parameters, a return value, or as a static or network function is never called; a setup warning in the Message Log names its class.

## Stay independent

Your plugin includes no Rolly Save header and lists no Rolly Save dependency in its `Build.cs` or `.uplugin`: the `SaveGame` flag, `Serialize` and the three function names are all Rolly Save looks for. Games without Rolly Save build and run your plugin unchanged.

## Keep saves loadable

A save checks each object the way a load will. One object it refuses ends the whole save with Invalid Data and a setup message that names the object and the reason, and the slot keeps its previous save. It refuses what a load would refuse:

- a `Serialize` override that writes before it calls `Super::Serialize`;
- values nested more than 64 levels deep (each struct, container element, instanced struct and property bag is one level), texts formatted into each other more than 32 times, or a formatted text that would display more than about a million characters in any language the player may switch to: a translated pattern that formats another formatted text counts each of its characters as a place that text may repeat, so such formats nest two or three deep at most;
- owned objects nested more than 64 deep, or a property bag of more than 1,024 properties;
- inside an instanced struct (`FInstancedStruct`) or a property bag, at any depth, a struct with a `Serialize` of its own, such as `FInstancedStructContainer`, or a property type the save cannot read through. They may hold structs of `UPROPERTY` members, soft object paths, gameplay tag containers, instanced structs, property bags and the engine's fixed-size math types: vectors, rotators, quaternions, transforms of each precision, integer points and vectors, GUIDs, colors and date times. A property of your class may hold any struct type.

A save file has bounds of its own, counted across every object saved into it: 262,144 owned objects, texts that display about 67 million characters beyond their saved size (an ordinary line such as "Gold: 1,234" counts about 100), 4,096 property bag layouts and 256 MiB of instanced struct and property bag values, the elements of arrays, sets and maps inside them included at their full size. The save stops at the object that would pass one, so keep large collections in arrays of structs rather than objects, and long logs as the values their lines are built from.

A `SaveGame` property of your class that holds an `FInstancedStructContainer`, or another engine struct that reads a type for each item in a `Serialize` of its own, saves and loads, but the check before a load cannot read inside it, and its saved data chooses the type of every item. Before your game loads saves from other players or machines, keep such items in a `TArray<FInstancedStruct>` instead, whose types and values the check reads and bounds.
