Inventory System Save System - One Object Spawns on Play After Being Destroyed

you can do that,

just if you Add an Actor on spawn, you need to Remove that actor on pickup.

that said the way i do it is this,

OnSave i iterate over all actors with SaveGameInterface and call an interface function that saves their logic.

OnLoad i Delete all actors with SaveGameInterface and respawn them from the SaveGameData.

this is a little inefficient but safer for complex saving.

How do I go about this? I’m not sure what blueprint logic to use. I’ve added the OnLoad part

add an interface to your actors you want to save
the interface can return custom savegame data if you want (worry about this late)
OnSave, GetAllActorsWithInterface->GetSaveData->AddtoSaveArray

OnLoad, GetAllActorsWithInterface->SendInterfaceMessageToDestroy
we use a message so we can override if we choose to.

the SpawnAllActors from AddtoSaveArray.

i’ll actually release a plugin that does all this soon but the above logic is pretty simple

1 Like

I’m sorry, I’m confused how to spawn the actors, and where to spawn them? This is what I have (I can’t find the information to plug the spawnActor without error)

so the missing key is GetSaveData

so you have an interface, in that interface make a function called GetSaveData which returns whatever you want to save,
this will be a struct with at least ClassToSpawn and Transform.

Your save array will be of this struct

when you spawn you have the Class/Transfrom ready from your SaveStruct

thats an example of how i do it

1 Like

Alright so I’ve tried to do so, I think I am understanding how to do this, but I’m getting an error, and when I load into the game, no objects spawn. Here’s how the blueprints are looking;

Save Inventory:

Load Inventory:

GetSaveData:

Here’s the error:

Blueprint Runtime Error: “Accessed None trying to read property As Save Data Level”. Node: Branch Graph: ForEachLoop Function: Load Inventory Blueprint: C_InventorySystemComponent
Blueprint Runtime Error: “Accessed None”. Node: Branch Graph: ForEachLoop Function: Load Inventory Blueprint: C_InventorySystemComponent

it means your SaveGameObject isnt loaded/valid

ie when you LoadGameFromSlot->Cast to your SaveGameObject.

also make sure when you load the the world is ready, a good place may be in the GameMode beginplay but after a small delay

Okay, that error is resolved. Now I’m having this error;

Blueprint Runtime Error: “Accessed None trying to read property As Save Data Level”. Node: Set Content Graph: LoadInventory Function: Load Inventory Blueprint: C_InventorySystemComponent
Blueprint Runtime Error: “Accessed None”. Node: Set Content Graph: LoadInventory Function: Load Inventory Blueprint: C_InventorySystemComponent
Blueprint Runtime Error: “Accessed None trying to read property As Save Data Level”. Node: Add Unique Graph: EventGraph Function: Execute Ubergraph BP Base Parent Item Blueprint: BP_BaseParentItem
Blueprint Runtime Error: “Accessed None”. Node: Add Unique Graph: EventGraph Function: Execute Ubergraph BP Base Parent Item Blueprint: BP_BaseParentItem
Blueprint Runtime Error: “Accessed None trying to read property As Save Data Level”. Node: Add Unique Graph: EventGraph Function: Execute Ubergraph BP Base Parent Item Blueprint: BP_BaseParentItem (this part repeated excessively)

which has something to do with the content being invalid, likely because it’s not in the level?
I’m sorry for my lack of knowledge on this subject- I don’t think I’ve successfully figured out how to make sure the world is ready, I’ve tried but there isn’t much information I can find on how to use the ‘is level loaded’ node, assuming that’s what you’re speaking of. Also, would it be benificial to create a loading screen while loading the level, assuming once the game is put together it’ll take a second to get everything together.

Here are my updated blueprints:
Game Instance: Game Instance posted by anonymous | blueprintUE | PasteBin For Unreal Engine

Game Mode: Game Mode posted by anonymous | blueprintUE | PasteBin For Unreal Engine

I can’t give thanks enough to you for continuing to help me through this, I know it’s probably not easy.

ah your gameinstance has 2 savegame objects writing to the same Slot, i’d assume the second overrides the first.

you can have 1 savegame object with multiple variables inside. otherwise level data i’d usually save to something like SLOT_LEVELNAME

you GameMode beginplay means the level has loaded however it will fire before some actors so the delay is just to ensure actors have initialized.

probably a better idea to keep the savegave stuff inside the GameInstance not the GameMode. the GameInstance could even load level data before you load the map

1 Like

Yeah, I was wondering about that. I have multiple savegame objects to organize between data saved, because there’s all types of data to be saved. Should I only have one? If I recall correctly, the tutorial I was watching created two, one for inventory data and one for level changes.
I’m slightly confused what you’d like me to move from the gamemode to the gameinstance, honestly I followed ryan’s save game tutorial, and while working with you on this, I’ve been building upon it with another tutorial that is supposed to be an ultimate save system, but I’m struggling to keep track of them now.
How would I save the data from the two savegame objects to one slot, or do I have to move them into the same object?

Also, is my code in my game mode and game instance doing the same thing? It looks to be. I think there’s some confusion for me about the two different tutorials and what they had me do. I started this one {https://www.youtube.com/watch?feature=shared&t=1238&v=7gfA-QO5pA8} which is where I believe some of the code is coming from.

The tutorial above had me call it something similar to SLOT_LEVELNAME which you can see in the game mode.

you can have multiple saves but i think they’d need to be in a different slot.
or use the same save with different variables, ie mapdata array/player data array

yeah the issue is just you have both for some reason. Get rid of one, doesnt matter which. Personally i prefer GameInstance so some data can carry across levels such as PlayerData but either is fine

you can have multiple saves but i think they’d need to be in a different slot.

So I’m assuming this mean I can’t save player data and level data at the same time, so if a player loads a slot, will only one load unless I add them to the same save?

So because of this, I’ve tried to create a savegame object that will combine the other objects when the save button is pressed.

This is what I have so far, but I’m not sure how to combine the save and load inventory functions with that savegame. I tried moving things around to be a bit more cohesive, I hope I succeeded and didn’t make more of a mess. I replaced all references to player data and level data to the saveData_MEGA and moved all their variables to it as well.

Here are all my blueprints that have underwent some big changes (many others have had variables replaced, but because they were ALL replaced, they should work the same I believe)
Parent Item: Parent Item - Event Begin Play posted by anonymous | blueprintUE | PasteBin For Unreal Engine
Save All Data (inside instance): Save All Data - Game Instance Function posted by anonymous | blueprintUE | PasteBin For Unreal Engine
Game Instance: Game Instance Event - Init posted by anonymous | blueprintUE | PasteBin For Unreal Engine
Inventory System Component: Inventory System Event Graph posted by anonymous | blueprintUE | PasteBin For Unreal Engine
Save Inventory: Save Inventory posted by anonymous | blueprintUE | PasteBin For Unreal Engine
(All made in 5.4)
{and the game mode doesn’t have anything inside of it anymore. My Load Inventory function I moved to the game instance, and I removed the containers added part because I don’t believe I’ll be needing that)

Sorry, I still am not sure how to make sure when you load the the world is ready. I’ve tried but there isn’t much information I can find on how to use the ‘is level loaded’ node, assuming that’s what you’re speaking of. I removed it from the BP for now.

I tried to remove everything unnecessary and the autosave functions (only saving from the save button) though I’m unsure if I did so efficiently.

So the current state of the game: It doesn’t seem to be saving anything, but my items are back. Everything is working other than the saving, like my ability to pick up, move items in inventory, talk to characters, everything it’s meant to do… without saving. My Project > Saved > SaveGames folder has two SAV files, MainMenuMAP_Data.sav which is what I’m meant to have, I believe, nothing is actually saved to them, though.

I’m wondering- I’m not sure how the loading things up work. Is it something that ACTUALLY saves the state of the game, or does it just save the data like variable values, and you have to actually set everything to the saved variables in order for it to show up when you load the game again?
Hopefully this was cohesive enough for understanding.

this makes sense though since PlayerData persists between levels and LevelData is only relevant to the current level.

this is always tricky because it depends on your game, the hacky way is to use a delay on GameMode/PlayerController BeginPlay. The proper way would be to have some sort of manager check if the things you want loaded are actually loaded.

For testing just use the hacky way ha

this is the way

ParentItem - Delete all code, node needed
SaveAllData - use IsValid check on Inventroy to make sure you’ve set it.
GameInstance - You cant use EventInit, this happens once and before the world has loaded, put it in a function called LoadLevel and call it when your world is ready.
Also Delete ActorsRemovedLoop, this is redundant now.

the rest is hard to follow so start with that, and refer to my pic above, thats all you need to start

You mention sending an image, I’m not seeing any though. I’m still not sure how to use the load level check. What do I use as the target? The level, obviously, but I’m not sure how to get the level. If that makes sense. The only node I could find to plug into ‘target’ is ‘get streaming level’ and that causes this error: (although when in game, it prints levelloaded as false.

Blueprint Runtime Error: "Accessed None trying to read property CallFunc_GetStreamingLevel_ReturnValue". Node:  Branch Graph:  Check Level Load Output Function:  Check Level Load Output Blueprint:  BP_SSGameMode
Blueprint Runtime Error: "Accessed None trying to read property CallFunc_GetStreamingLevel_ReturnValue". Node:  Return Node Graph:  Check Level Load Output Function:  Check Level Load Output Blueprint:  BP_SSGameMode

Updated Blueprints:
Main Menu On Clicked (Start Button): Main Menu On Clicked (Start Button) posted by anonymous | blueprintUE | PasteBin For Unreal Engine
SSGameMode check level load function: SSGameMode check level load function posted by anonymous | blueprintUE | PasteBin For Unreal Engine
Game Instance: Game Instance posted by anonymous | blueprintUE | PasteBin For Unreal Engine

i dont think your map is a streamleveling, for now just use GameMode BeginPlay → Delay 0.2 this isnt great but lets get everything working first.

i assume your mainmenu is a widget? dont do any logic there it could get destroyed on levelload, just call a function in your GameInstance. The PlayerController stuff should just be in the playercontroller, likely on begin play.

GameInstance is fine for now but no need to save after loading, and no need to cast to GameInstance since you are the GI

1 Like

Yes, my main menu is a widget! I moved the code from that to this function in the game instance.

This is the code left in the Main Menu if that is relevant. I would remove everything off of the start game button, but then I don’t understand how I’d call the function that the button was pressed.

both look good!