I’ve used save games in the past but I’ve never looked into saving a large amount of data into save games or saving data into a drive if possible using blueprints. Researching the topic everyone talks about saving variables but how would save a large amount of data into save games without 1000 variables? If it’s even possible to save whole levels so when loading it will spawn everything that’s not already in the world using the save game. To Summarize Can Someone Explain More In Detail About Save Games And If There Are More Uses Than Just Saving Variables? I’d Appreciate It, Even If It’s Bad News.
tl;dr: there are plugins that do the below and much more.
Even If It’s Bad News
It’s mostly bad news - it’s just variables. But it’s not ALL bad news - you generally do not save individual variables one by one. You save structs. Arrays of. Arrays of nested structs, too. And you write script to automate it. And you write script to load & restore it. It’s a lot of upfront work that becomes somewhat efficient once the pieces are assembled.
Lets say the player crafted a Fiery
Sword
of Burn It All
. The player has also hoarded 4569 enchanted weapons at home, in the chest.
Each sword has a single struct variable consisting of the following:
Name
Enchant Prefix (fiery, ice, cappuchino)Class
Melee Weapon (sword, axe, whip)Name
Enchant Suffix (of Burn It All, of Whipping Real Hard)Int
DamageFloat
Durability (0-100)Enum
Container (backpack, ground, held in hand, chest)String
Friendly User Name (so they can rename it)- a couple dozen more, surely
When you’re ready to save, you loop through currently spawned weapons, fetch their structs and add them to an array. You then loop through the player’s armour pieces and fetch their structs, too. Don’t forget to fetch structs of items that are in the world but are not spawned - as in, there’s no need for every shopkeeper and their mother to have a selection of spawned Actor Pickaxes. But they do hold onto a list of structs that may turn into Actor if needed.
Each container can have a function that returns its content. A backpack can return an array of structs of items the player is carrying. The shopkeeper’s shop has that list already. This would automate the process - especially that you can loop over all the shopkeepers in the world and fetch their lists.
Once you have all the arrays of structs ready, push them into the Save Game Object and Save to Slot.
When you load the data, you start iterating through the arrays you saved. You loop over the 4570 weapons (the last one was held in hand) and start respawning the ones that need respawning (stuff in the chest does not need respawning until you open the chest).
Read the array of weapon structs and check the Enum
Container (backpack, ground, held in hand, chest). If the item is held in hand, then Spawn the Actor from Class and give it the struct you’ve just read. Have the actor reconstruct itself using the data you’ve just pushed into it.
- use
Name
Enchant Prefix to fetch the effect from the appropriate data table - check value of
Float
Durability (0-100) and apply a material parameter to the mesh - use
String
Friendly User Name (so they can rename it) to create a tooltip widget - and so on…
Each spawned actor can do it for itself. Or you can have a dedicated actor managing saving / loading.
This whole thing above is greatly simplified and many methods exist. Apologies if it sounded a bit silly.
Making simple games is hard. Making complex games is… well, you know - even harder. One person doing it all is pure labour.
But how would I save actors, their
components, the location of every
component and everything about the
actor and when you load the save how
would you spawn the actor with all of
the info efficiently?
The actors already have components when you spawn them. It’s a matter of configuring them in a specific way using variables. If they were dynamic, you already have the functionality to add them, so you’d use that. I feel I made it sound worse than it is.
You generally write 1 load / save function per class, inheritance helps a lot. The base class knows how to save shared variables, the children can call parent’s save functionality first, override with their own and spit out the result.
Never used a plugin for saving, can’t really recommend anything specific. I know this exists:
https://forums.unrealengine.com/unreal-engine/marketplace/1467088-plugin-savior-3
And this seems to be free, highly rated and up-to-date:
I should of clarified, I meant something like on begin play add a new static mesh onto the actor then saving the actor with all of the data, locations, materials, mesh, collision, and again I don’t use plugins until I understand most on how it works. The save extension plugin says it saves everything or something like that, and I have no idea how to use it and I don’t know the details on what’s it saving. I’ve heard that saving takes a lot of space for the smallest things.
No not at all silly, its pretty much what I expected. But how would I save actors, their components, the location of every component and everything about the actor and when you load the save how would you spawn the actor with all of the info efficiently? Or maybe when loading it will revert the world to the save point. Where does the sabe take place, on the pc or on somewhere else? Also I would love for some recommendations for plugins, especially free ones. Although I feel bad using plugins without havin some idea of how it works. Thanks!
I meant something like on begin play
add a new static mesh onto the actor
If you’re doing that, you probably have some rules that dictate which mesh goes to which actor, right? You’d do the exact same thing in the load function. Normally you keep those rules in the data table - data tables use structs. You fetch a row from the data table, and spawn an actor based on that data.
When loading a game you’d fetch the struct from a save game object instead.
There’s little else I can add it here, wish I could. You pack all the data you need into a struct. You pack those structs into other structs. You make arrays of those structs and you run everything in loops.
There is no other clever solution in blueprints, hence the popularity of the save plugins. Sorry.
I’ve heard that saving takes a lot of
space for the smallest things
Kind of. I just went on and saved 100000 transforms for ■■■■ & giggles. So that’s 900 000 floats packed into a neat struct. That’s under 25MB - bloated but not too bad.
How would I achieve something identical to nested structs but with having structs nested so I could edit the first struct without fear of the second one corrupting? Data tables I may use. I do wish that unreal had more save functions like “Save whole level” or “Save whole actor(Including locations etc.)”, and please let me know if you find more plugins that are easy to learn and use, but are really useful. Also, where would I handle the saving functions, in the save game file or whatever it is, or an actor, or something else? I don’t want to copy and paste save functions everywhere to save, or is there any way I could use an interface but have it run something like a global function, so I don’t have to again, copy and paste the functions?
Well if you do have any idea on nested struct alternatives please let me know, I do hate having to save the project and making a backup every time I want to add or edit one variable in a nested struct. But still, where should I have the functions for me to use globally? In the save game actor or file or whatever, (The place where you store the variables to save) or something else?
Out of sheer curiosity, an array of 1 million of these, with some randomised data:
…is less than 9MB - not too shabby.
Not sure. I’ve been using nested structs with few issues since 4.22 - that was the last time I experienced a major breakdown. Although I do take care when editing structs.
I do wish that unreal had more save
functions like “Save whole level” or
“Save whole actor(Including locations
etc.)”
Would be sweet! UE5’s must-have feature, for sure.
plugins that are easy to learn and
use, but are really useful
I’m not into plugins (the extended library is the only exception); do not feel too comfortable when I don’t know how things work under the hood. And yet here I am connecting colourful wires to nodes that perform seemingly magical things
But still, where should I have the
functions for me to use globally?
Game Instance is a good choice.
I’ve never heard of game instances, I’ll look into it.
EDIT:I’ve looked into game instances and seem useful, kinda like a save system until you quit the game, I’ll probably leave the question unanswered but Thanks for your input!
Quick question: How would I save the actors and the variables? If I load them and the same actor exists, how would I update the components and variables? Or add the components from the game instance?
Thanks for replying! Is there a way to add the actor components from the game instance? Or call an interface event but the target actor is undefined?
No, but that should be a part of the actor’s update, you push in the data and the actor takes care of the rest:
If I load them and the same actor
exists, how would I update the
components and variables?
Have a function in the actor that takes and sets the actor’s struct. The actor can then manipulate its own components any way it needs.
Ok Thanks!
I tried out nested structs but instead of just two structs I used a struct and a map with a struct as values, I’ve edited the 2nd struct twice now and nothing got corrupted! It may be luck but idk.
Another Question: Let’s say I saved multiple actors from the level into an array. Then I quit the game and load the array. How would I tell Unreal which element belongs to which actor? I’m currently using display name but it doesn’t sound the most efficient. Please respond with something that can support multiple actors of the same class. My save system is coming along now, I’ve been able to have an two events to call to save and load everything all at once with a save interface and it supports multiple levels by indexing numbers according to the levels at the end. When I finish the save system I could reuse it and set it up easily in future projects and I’d understand everything about it cause I built it! Thanks for your help so far!
Moving it here so there’s more space for the chunky screenshots and I don’t get logged out all the effing time
Let’s say I saved multiple actors from
the level into an array. Then I quit
the game and load the array. How would
I tell Unreal which element belongs to
which actor?
I would not use the Display Name
for this. You could use a [Map][1] (a.k.a. Dictionary) to identify actors efficiently. Think of the Map as if it was a Data Table but you do not get to use a snazzy interface. It’s a list of uniquely named things. There is a Key
& and a Value
associated with that key.
The one on the left is Name | Actor - it keeps a list of actors to find; the one on the right is Name | Struct - that’s the one we’re going to save and load.
I have those 2 boyos in the level:
They each have a data struct, one of the variables is their Unique Name. And Roger Says Hello.
When I’m ready to save:
- grab all actors that need saving and put them in the Map variable, using their Unique Names as keys: the
CreateActorsMap
Event - first I modify what Roger has to say so there’s something to save
- create a save game object
- step through the Name | Actors map, read actors’ structs and push them into the save game’s Name | Struct map
- save to slot
When I’m ready to load the map and restore any saved actors from this level:
- once the map has been loaded
- create the a Name | Actor map of existing actors in this level, using the same method as before
- load the save game object, step through the Name | Struct map
- use the unique name to match an actor in the level
- if the entry does not exist, this actor was not a part of the level, it needs to respawned from scratch and then given the struct
And while you can do a similar thing with an array, with the Map you get to choose by name. If you need to find a particular actor (5 of 5000) and only update those, you can; rather than loop-break through a 5000 element long array and compare names.