[PLUGIN] Savior

Thank you for your help! The shelves are now being saved and loaded properly. Nevertheless, I’ve tried to use the same method in order to save the player’s inventory but without any success…
The player’s inventory is a custom component I’ve created and added to the player’s actor blueprint class. The component contains a map variable I’m trying to save. The player’s actor seems to be saving and loading properly though, because the gold amount the player has is being saved and loaded successfully.

If you are trying to save a map of actors.
I’ve only implemented Maps of:

<Object|Object>
<Name|Object>

If your contains references to actors you should convert those references to Soft References instead.

The will print to output log if a map can’t be saved.


It’s still in my to do list to include other types of maps when there’s objects hard references in them.

You can edit records by hand:

The map I was referring to is a map of:
<integer|integer>
Can this map be saved?

Yes. If that isn’t loading you have to check the output log for clues.

If the map property is marked ‘Save Game’ it should save.

I’ve managed to fix it and everything works perfectly now. Thank you for your quick responses and all of your help :slight_smile:

So I’m confused again. I was under the impression I could create 2 instances from the base slot. LocalSlot is the empty slot and LocalTempSlot is the slot I want to read data into. I then want to selectively copy records from the LocalTempSlot and add them to the empty LocalSlot. However it appears that when I read data into the LocalTempSlot, it also loads data into the LocalSlot which I don’t want. LocalSlot has 0 records after creating it via NewSlotInstance, then when I read data into the LocalTempSlot, somehow the LocalSlot gets the data as well.

I’m not sure what you’re doing, but seems to me you want to erase data from the splash screen for whatever reason (there’s a copy of data to a static slot when Unreal displays a loading screen and loads a new level):

if ( UGameInstance* const & GI = GetWorld()->GetGameInstance() )
{
	if ( USaviorSubsystem * System = GI->GetSubsystem<USaviorSubsystem>() )
	{
		System->Reset();
	}
}

I just want every save to only capture the current state of the game, with the ability to selectively copy records over to the new (empty slot) that I want to persist from the current slot.

So I think you want to remove this line from ReadSlotFromFile():

USavior3::ShadowCopySlot( this, System->StaticSlot, Result );

Removing that can cause bugs if you use “Reset Level on Load” option.

Hi,

I have just a quick question.

I am using SaveGameWorld / LoadGameWorld and find that a lot of my scene is being saved in the .sav file. Things such as StaticMeshActor, TextRenderActor, PointLight etc. These are often things that are just making up the walls, floors and basic lighting that does not change.

Do I have to add !Save and !Load to every single one of these actors from now on, or is there a way to exclude a class from the Save process?

Thanks

Open your Slot class from Asset Browser and edit your Scope sections:

Only child class of the classes you pick will be saved.

Hey there,

Can you share with us some tips & tricks for serializing HISM’s with thousands of instances, how would you go about that?

We need to save & load thousands of dynamic foliage components that were added/removed at runtime.

Cheers!

None of their native properties have a ‘Save Game’ tag and you can’t mark them manually.
You have to either create a custom c++ child of that component or create mirror variables in your blueprint that you later apply to your component:

UInstancedStaticMeshComponent | Unreal Engine Documentation

I wouldn’t do this in blueprints tho.
I would create some custom serializable c++ component (containing SaveGame UProperties) as a wrapper/manager that can access native properties and easily save/load them and apply to the actual HISM.

For things like this it’s good to avoid blueprints and go into c++ directly.

Hey, @BrUnO_XaVIeR thanks for your reply above.

We have another question: It seems that your plugin can only support serializing/deserializing from one SaveSlot at a time like there is only one active static SaveSlot based on your implementation in the SaviorSubsystem StaticSlot.

Is it possible to have a SaveSlot for each major system such as Player, AI, Quest, etc.?

We would like to serialize & deserialize each of the mentioned systems separately at different stages, but your implementation doesn;t seem to allow for that flexibility.

Cheers!

That only matters if you use save/load world nodes.

You can create a slot class (on asset browser) for each type of data, setup their Scope filters to only accept the classes you need and do something like:

New Slot Instance >> Save Actor(s) >> Write Slot to File

For each of your slots.
However that will execute on Game Thread, not async.

Hey! I’m having some trouble getting the game mode to load it’s data. I’m using the load game world node just like the demo, but the game mode’s variables are all empty. I’ve set the SaveGame value to true, but they are all still empty.

Also, I create my player character during runtime and possess it. Right now, I’m able to load a game and my player character is loaded in the correct position. But the actor is not possessed. Is there any way I can possess the player character? Nothing I’ve tried seems to work

The plug-in doesn’t interfere with actor possession. You supposed to do that yourself.

You have to start a level, possess your character then use Save/Load Game Mode.

My actor is possessed when I save the game, but when I load the game the character exists (I can see it by spectating) but it’s not possessed.

Also what about the Game Mode variables? They don’t appear to be loading even though I’m using the load game world (async). I tried waiting a few seconds and checking again, but they really aren’t getting set.

I would use Save Game Mode and Load Game Mode instead.

Also give a SGUID property to your classes.
Set their value to a valid Guid number in editor or use a Make SGUID from constructor.