Satisfactory style game saves for spawned items and buildings.

Hey again all!

So as the topic title suggests. I would like to get opinions on the best way to go around saving things that players create in the world im building. As im fairly early on i thought it might be best to hit this head on before it becomes too messy at a later date.

So, the question, how best to save buildings and the like, especially when each building may have storage, settings, possibly power connections etc etc.

What is the best way to ear mark them for saving (obviously this cant be manually as they are created at run time). An how would one go about saving all the individual settings within each actor? Can an actor and its settings simply be found by say its class or tag and saved with all its settings in one go? Or do i need to tailor a specific way to extract all the settings from each actor?

Any advice or pointers would be gratefully appreciated.

Satisfactory being based on unreal engine seems to do this in a very fast manner so its possible. I will have way less to save. But still complex nonetheless.

1 Like

Yes, you need to do that :slight_smile:

It’s all to do with the save game object

It’s really up to you how you do it. I would recommend making everything blueprints, so they can save themselves. Because trying to do everything from the level blueprint will take years off your life :slight_smile:

If you can’t face it, you can use a plugin, which add components to actors, then take everything else off your hands. Well known ones are

2 Likes

HAHA years indeed. So when you say save themselves, you dont mean they grab a life preserver and swim for the shore, so are you talking seperate save files per BP actor?

Or is there a master save file that they communicate their settings to?

Ive seen the save game object but have never really had the need for it as such. So i need to kind of find the best way to utilise it. Good job i enjoy challenges. I do have a few ideas in mind but until i start playing with the save game object and find its limits who can tell if they will work!

Tempting, but where would be the fun in that? :rofl: Though its food for thought!

1 Like

By ‘save themselves’ I mean each BP will save what it needs to the Save Game, when it needs to, and load again ( probably on begin play ). So you don’t have to try and orchestrate it in one massive nightmare on acid script :slight_smile:

How exactly you do that, is really up to you.

I made a whole game where each actor ( that needed info ) only needed some vectors, float, bools, that kind of thing. Once save game, which just had a lot of stuff in it.

You might want to write your own actor component which you can add to anything that needs to know how to use the SG, and what to save. You might also make a parent class that knows how to save, and all the actors that need that, inherit from it.

It’s really a ‘how long is a piece of string’ type question :slight_smile:

1 Like

Thanks for a very good insight to how this would work, i like the idea of updating the save from blueprints progressively in some manner.

I appreciate the detailed explanation.

1 Like

I am using the built-in system to save hundreds of thousands of items and I can share some thoughts on what I am doing and what I am considering:

What I am doing now:

First I use a GUID for every save-game object’s key. My base class has this method so everything inherits from it.

I have 2 savegame objects. One for player made stuff which starts small and will likely grow to a few thousand things by end-game. I have another for procedurally generated content that I want to restore every time the player loads the game. In addition, this content can be removed by the player’s actions, so it is dynamic. This file has around 350,000 objects in it which are just a GUID and a transform.

Saving to the large file would make a noticeable hitch in frame rate so instead I save transactions to the large save game file in the normal savegame file (basically a list of entries I need to remove). Then on next load game I purge them from the large savegame file.

As I mentioned, all of the entries use a GUID as the key. Each savegame class gets its own struct in the savegame file. These structs are organized into Maps (the data type kind). Through polymorphism they each get a chance to save/load their data during the save/load process and they access the Map via their key to read/write.

Downsides

This approach causes data duplication because not only do the actors have their data, it is stored in the savegame as well. In addition, there is a data collection process to save the game before writing it to disk. Writing to disk is fast if the file is reasonable (20-30 meg starts to become noticeable) but not when it is 150-200 meg like my large savegame file. Hence the need for the transaction trick I mentioned.

What I am considering

If I replace the map system with simple arrays (keeping the GUID as a key still, but changing how it is stored in the savegame file, then I can have the load game process give each actor its index into the array. Then the actor can locally store the reference to the array and the index it uses. Through the use of Get->ByReference the actor can then store all of its local data right into the array, eliminating the need for a collection process. When the savegame timer comes due, it simply writes the file. Actors that are removed would just be marked as dead since reordering the array would be dangerous and costly. On the load process dead entries would be purged.

Final thoughts

Everything I made was done in blueprint and is more performant than I expected. The tools Clockwork mentioned would likely be vastly superior in speed because of how they save, however I have tons of object references in my hierarchy and those all have to be manually handled and I didn’t want to go through the overhead. I also had an issue getting RamaSave to work on a vanilla 4.25 project at the time since there is no longer support for that decided I didn’t want to rely on 3rd party stuff for this. YMMV.

Good luck with this. Savegame is a pain in the butt to handle and spending time on it means not making the game. So try to find the solution that has you spending the least amount of time on it you can.

1 Like

Thank you @mmcmain

The use of guid as an identifier was a thought i had. So you mention structs. So you create one for each say for instance building type to hold all the relevant information. So is there a reference to the unreal class in there to rebuild the correct asset? Or can you just pass the entire uasset to the savegame and it will save every last detail?

My problem lies in the intricaces of interconnects. Cables etc they connect power to buildings so need references to actors, to connection points on the actors (just components) so you get the issue , alot of data to restore an asset to its working condition including its working variables if the building produces or uses anything.

Whats the best way to encapsulate an entire actor and its variables so they can be dynamically recreated (as they are player created)

I will be going more likely into the 100s rather than 1000s so the overhead shouldnt be too great.

Thanks again

Each actor class has its own savegame struct. So in my case, I have a base class I call AttachableBody that allows stuff to connect to it. It saves the transform, the in-game UIName, physics info like direction of travel, and it also stores what children are connected to it.

Then I have ConnectablePart. It derives from AttachableBody but can be connected to other parts/bodies. It has a reference to the parent it is connected to, what socket it uses, etc.

Then things get more specific. For example Refinery has the settings it cares about: Configured Temperature, Current Temperature, etc.

Virtually all of my characters are player created and my level is nearly empty. So all of this is dynamically created. AttachableBody has two methods called SaveToSavegame and LoadFromSavegame that get called at the appropriate time. Each actor that cares about saving its own state overrides that method, asks the savegame object for its copy of its savegame struct (using its guid and accessing the map associated with its struct data). Then it simply copies the data to/from its member variables.

That is where the data duplication exists. It is both in the savegame struct and the member variables of the actor.

Keep in mind your savegame object is capable of saving and restoring complex data, just not memory references. You can save arrays, structs, maps, etc.

Here is a screenshot of a portion of mine:

As you can see there, HISMRemovalMap is the map of objects I need to delete from the monster savegame file that contains around 350,000 HISM transforms that I generated at game start. For that I use the world location as their key.

This is what AttachableBody’s structure looks like:

One further note:

Notice how I store the class in AttachableBody? That is how the LoadGame process knows what class to instantiate when it restores from a savegame. Then through polymorphism, each level of the class hierarchy gets its shot at the savegame data. In this case, the requirement is that all savegame objects derive from AttachableBody.

If I was starting over I would do something I that is currently on my TODO list for savegame: I would make a new base-class called PersistentActor that contains most of what is in AttachableBody (minus the child references, etc.) That will easily allow me to have things I want in the world that are not AttachableBody’s live in the savegame system.

But for now, I am busy on game content and re-architecting things is a never-ending saga.

thanks @mmcmain

Though all the information from tutorials and @ClockworkOcean has underlined show me how the save game works. What it doesnt show is how complex it can be. Most tutorials all point to basic save data ie player stats etc. But looking at that lets me get my head round how complex you can make it as @ClockworkOcean did explain i would need to probably get creative for the most part.

i would have to load things in a natural order, ie base buildings first , then inventories and connections etc and anything that relies on another entities.

This could be fun (and long!) but im early on with this project so i can make changes now so not to upset the apple cart months down the road with a head slap moment :face_with_head_bandage:

Much thanks yet again to both of you!

2 Likes

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.