You can find many UProperty flags in the engine docs:
I bought a plugin, and I have no idea, where to start, lol xD I have player and inventory component on the actor inside level. So, I want this inventory to be saved. I expanded inventory class with public ISAVIOR_Serializable; Added FGuid SGUID; For the struct I want to save inside the inventory actor component, I added “SaveGame” as metadata of UPROPERTY(). But … No matter what save/load methods I used, inventory is never saved. Like, what is the most super simple way now to make sure, that I can make some changes to inventory, click “save”, then exit level, start it again, click “load”, and see the changes? So far, I created slot inside Editor, and I am saving to that slot all the time. But I fee this is somehow wrong xD Also, inventory component attached to actor inside the level, maybe that is an issue? If I want inventory to persist between levels, it needs to live inside GameInstance variable or something? But in case, right now I am working within single level, but SaveLevel, Save World, SaveGame mode e.t.c. not helping, hmmmm
There’s a sample inventory BP in the demo project.
I’d suggest you take a look on how the Serializable interface is used on it.
You also have to make sure that the properties to be saved have the ‘Save Game’ checkbox marked on, under ‘Advanced’ section of your BP details.
Ah, alright, will do! Its just that I am using Inventory Framework Plugin, and dev said its already configured for Savior, marked with SaveGame, but maybe that is not enough, I’ll then take deeper look into the simple inventory example
If you still have issues, you can send me a zipped Blueprint and I will setup for you so you can have a grasp of what may be missing.
After you get used to it, it’s really very simple to use it.
Unfortunately, yes, I am still getting problems.
So, fir the Inventory class, I have
UPROPERTY(Category = ID, EditDefaultsOnly, BlueprintReadOnly) | |
---|---|
FGuid SGUID; |
and also extended it as
public ISAVIOR_Serializable;
The property I am saving itself is marked with SaveGame
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Settings, meta = (TitleProperty = ContainerIdentifier), SaveGame) | |
---|---|
TArray<FS_ContainerSettings> ContainerSettings; |
I also added this code for SGUID:
UAC_Inventory_Extended::UAC_Inventory_Extended() {
if (HasAnyFlags(RF_ClassDefaultObject | RF_ArchetypeObject)) {
SGUID = USavior::MakeComponentGUID(this, EGuidGeneratorMode::StaticNameToGUID);
}
else { SGUID = USavior::MakeComponentGUID(this, EGuidGeneratorMode::ResolvedNameToGUID); }
}
So, this concludes the setup, its 1:1 as SimpleInventory example.
Then, I used this very simple blueprint setup to save/load:
It saves with success. When loading, I see, that some data inside Editor inspector gets updated, but then everything immediately crashes with error:
“Assertion failed: IsInGameThread() [File:D:\build++UE5\Sync\Engine\Source\Runtime\CoreUObject\Private\UObject\UObjectGlobals.cpp] [Line: 1580] Unable to load /Engine/Transient. Objects and Packages can only be loaded from the game thread.”
I feel that I am missing just some tiny little thing there… Error is the same with non-async functions too, with those I just copy from Example project.
Btw, if I tick “Reset level on load” option, then it still crashes on load, but with different kind of error:
Fatal error: [File:D:\build++UE5\Sync\Engine\Source\Runtime\Engine\Private\LevelActor.cpp] [Line: 583] Cannot generate unique name for ‘ChaosDebugDrawActor’ in level ‘Level /ShooterCore/ABCore/UEDPIE_0_ABWeaponEditor.ABWeaponEditor:PersistentLevel’.
Your setup seems to be trying to save objects outside of the game world (editor assets).
I would try to use save/load actors array with specific classes set.
Or edit the project settings - Savior configs, to make sure that these BPs that exist outside of your game world are not read by the entity scanning process.
Thanks! I’ll try ‘I would try to use save/load actors array with specific classes set.’ and see how it goes
Hello!
I’m working on integrating the Savior Plugin into my project. I’ve implemented saving the world with SaveGameWorldAsync and reloading it on game restart using LoadGameWorldAsync.
However, I’m having a problem when dealing with adding actors to the world after a save and then trying to reload the previous save. Here’s the scenario:
- I load into the world adding a few actors.
- I save the Game World.
- I Add a few new actors.
- I want to load the Game World to restore it to point “2” in this list.
While LoadGameWorldAsync resets existing actors to their saved states, the newly spawned ones remain. I’ve tried both OpenLevel followed by LoadGameWorldAsync and using LoadGameWorldAsync alone, but neither achieves the desired result.
Is there an efficient way to restore the game world to its previously saved state, including removing actors spawned after the save point?
To me it sounds like you want to “load world” while reseting the state of the levels.
You can manually reopen the level before loading the data or you can try to use this node and make sure that the “Reset Level on Load” option is checked:
Thanks for the response. I was already trying to do that.
It seems like I had to add a delay node (of one frame) between the “[SAVIOR] Load Game World”(using “Reset Level on Load”) and the “[SAVIOR] Load Game World” call, it does not seem to be able to perform both loads in the same Event sequence without a delay in between them.
Without a delay it seemed to only perform the “[SAVIOR] Load Game World” (using “Reset Level on Load”) correctly so the level got to its initial state without any saved changes being applied.
Do you think the Delay node should be necessary to be used between the two calls, or should it be working without a delay of one frame?
If you want to perform multiple loading operations, then you need to do it in separate frames. So a delay is needed, yes.
Without a delay the system will report it is already working on a loading operation and cancel the new call.
Hey! So, I found something that seems like a bug, but I’m not entirely sure if it’s just me misunderstanding how Savior should work. My bad if that’s the case - I’m still getting the hang of it.
Here’s how to make the ‘bug’ happen:
-
Create a new blueprint class with a static mesh component as the root (I called mine
BP_SpawnableCube
). Do the required steps needed to save dynamic/runtime spawned actors (SGUID and implement procedural interface). -
Create a new
Savior (Slot)
in the Content Browser. -
Setup events for spawning
BP_SpawnableCube
in a random location, saving, and loading. See image below:
I put the events in the Level Blueprint for simplicity, but I experienced the same problem when I had the code in the Game Instance. -
Play the game and spawn 3 cubes in runtime. I will refer to these as cube A, B, and C.
-
Save the game. Exit the game.
-
(This is the step that ‘causes’ the bug, if I don’t do this step everything works as expected.) Right click the Savior Slot in the Content Browser and select Save Data Explorer to visualize what is saved in the save file. Close the Save Data Explorer.
-
Start the game again and spawn 1 cube (Cube X). Save and exit the game.
-
Start the game and load the save. You will see 3 cubes spawning. Cube X, B, and C.
At the last step I expected to only see 1 cube spawning (the one from step 7) since that is the behavior when not opening the Save Data Explorer. My understanding is that Save Game World normally overwrites the previous save. Correct me if I’m wrong.
Deleting the save file and meta data file physically on disk and then starting from step 7 again will still result in 3 cubes loading/spawning. Restarting the Unreal editor seems to ‘reset’ (sometimes, but not always) the save slot back into “normal” behavior (same behavior as if never opening the Save Data Explorer in step 6).
Hi Bruno,
We are using LoadGameWorldAsync to load our GameWorld which consists of dynamically spawned actors.
When performing the LoadGameWorldAsync it does not seem to perform the Loading async for us, even though BackgroundTask is specified as RuntimeMode in the Savior Slot. Instead the Game Freezes on LoadGameWorldAsync and then all actors pops into existence after the Frozen Screen. Our current scene is a small scene with only around 10-20 spawned actors. We have also set the Actor Scope to only save our Dynamic Actors base class. So our current Save file is very small only around 60 KB.
We have also tested to save and load the Dynamic Actors in Level 3 of the UE5 Savior Demo Project (linked on Savior Plugin store page).
There we also get a similar experience when pressing the Load Slot button and selecting a Savior Slot that has specified BackgroundTask as RuntimeMode. It seems to Freeze for a couple of seconds and then all actors get spawned, with around 10 dynamically spawned actors in the Save file.
Also no Loading Screen shows up even though we specified it in the Savior Slot.
Is this the expected behavior when loading Dynamic Actors? (That the game freezes for a couple of seconds)
(The tests were performed on a computer with an SSD so I don’t think the loading from Storage should be that slow.)
(We seem to get the same issue on two different projects, the SaviorDemoProject using UE 5.0.3 and our own project using UE 5.3.2)
Any chance you can send me that test project?
You might see a freeze due to actors being spawned into the world.
But I could go through the nodes and add comments for you (and make modifications where needed so you can take as reference).
Okay, so this is a problem caused by the save data explorer window.
Because it loads the save data to the slot memory and keeps it there until that data is erased again (it loads the data just the same way the runtime game does).
I will work on a fix for this.
We have a simple test project where it is happening for us that we can upload to google drive and share the link with you over email. Together with more information about the freeze we are experianceing together with a video how it looks for us (In case that you are not experiancing any issues at your end when running the project).
Would this be ok?
I got the project files and I am investigating the problem.
Thank you!
Hi! Does Savior work with the open world? I’ve downloaded the sample project, created a new open world map, placed actors that were included in the demo, and attempted to save/load. As a result, the actors’ state wasn’t restored after the load operation was completed: I’ve picked up a few bottles and collided with some actors, and after loading, they were all restored on a level. Here is the video. I suppose that it should work, because data layers runtime state restores fine. So maybe I’m missing something
The API for actor proxy (used by open world maps) is still very limited.
I am watching what Epic exposes to make them easier to work with, but right now in Unreal 5 only the state of data layers is saved/loaded.