Handling Saving Destroyed Objects between different Levels (HELP)

Hi there,
I currently have the issue that I am overlapping pickups and once I do so, I add them to an Array and on the next startup, the level BP checks whether the save exists and loops through the array and destroys the objects that were stored in it. I encountered the issue that switching levels the objects were not valid anymore which isnt an issue, but there were some bugs still. So my current approach is following:

Made a struct of an pickup array. When the string is level 1: get the 0th element in it and set it to collected items in the save. Then the loop destroys everything in that. The goal was to have an array for each level.

The issue is: it doesnt seem to save the elements, or doesnt seem to save the elements to the array causing the begin play for loop not to destroy anything. I am not sure what is wrong. I must say, working with BPS and struct is so much worse than it is with basic C++…



Don’t work with actor references, just use integer IDs. Each pickable object has an ID. When they are picked up, you put the ID in the save game.

On begin play, all these objects take a look at the save game, if they see their ID in there, they destroy themselves. That’s it.

what would be a clean way of doing IDs? The biggest issue I have is level switch. I currently implemented it like so: gameinstance has an int of collected ids. Begin Play on Pick Up will the game instance counter, add 1 to it and set the counter value to id. However, the issue is when deleting or shuffling objects, or just the nature of when begin play is fired, i fear the ids will be different on any play so some objects get an id which was counted as picked up while it wasnt. I wish BP had static class variables or something.

perhaps a way would be to turn get name to an integer value and save this or hash it but would be too complicated to me.

It’s really simple. Anything that can be picked up has an ID, like this:

image

When you put it in the level, all you need to do, is make sure they all have a different ID

If you have a lot of them, you can use another BP to number them.

Let’s imagine we’re on level1, you need an array of IDs to know what you’re picked up in the save game

image

When a BP gets picked up, it does this

And then on begin play

That’s it basically ( I left out all the messing around with the SG for clarity, there’s a great way of doing that with game instance, if you want to know ).

Some areas for improvement are:

*) Make a parent BP that contains all the common code and concepts for pickups ( ID, collision, mesh, particle effect, savegame code etc ). Then all your pickups can just inherit from that parent.

1 Like

ah, so it involves creating unique ids by hand. I think this would be indeed the least painful or error prone solution. Ill try coming up with a way to do it automatically.

edit:

Okay my current solution is inspired by some of your ideas but I did following : I am getting the name of the object + the current level name and the bool whether it was picked up in a struct. I save all this in the game save. On begin play each object checks whether name is == to own name in the struct AND checks whether this is the same level name which it was picked up in. Storing Object name alone could shoot me on the foot because I have some pick ups named same way in two levels.

HOWEVER, it would be awesome to have another way of getting an unique identifier for a level (please let me know if there is any). I really dont want to use the string name as its very prone to error if I change level name. Is there a way I can give each level a unique ID which I can store instead?

another edit:
I made a workaround by making a class called levelinfo, i made a public string and called it unique level name. I made a BP function library with the function that retrieves the unique name. If I ever have to change the name of the map, I make a function that will replace all instances in the array which contain the old name with the new name.

thanks!

Making the BP to set the IDs is cinch…

It’s a ‘call in editor’ event. You only run it once after you’ve put everything in the level.

image

does this ensure every object gets the same ID every time? If yes that solves the problem, I am away from the PC now but I am not sure if it does this. If it does this it indeed fixes the problem and makes it simpler.
So for instance i have 10 objects placed and I decide to place another 10. And run it again. Now in my save game the current stored ids may get mixed up because now an ID has been assigned to a different obj which wasnt picked up yet. The ID issue gets maybe messier when you switch level since the game instance would have to store the current max id(?). Sorry for all I am throwing your way in advance :smiley:

perhaps one could check if id has already been assigned and only assign a new id if it has a value of lets say -1 which is our representation for an unassigned id.

It goes like this

  1. Put all the stuff in the level

  2. Run the number BP - ONCE

  3. Save the level

That’s it. Because you saved the level, they all have the ID fixed.

If you later want to put more stuff in the level, you need to deal with that in your numbering BP. Yes, you can only number unnumbered BPs, for example.

1 Like

you could simplify this and use the game instance blueprint. variables on this blueprint will not get destroyed between levels.

but with power comes great responsibility so careful what you save or reference in this blueprint

You can’t use the GI, because it doesn’t survive a restart. That’s why we’re talking about the save game :wink:

Have you thought about maybe just storing the collected object guid (global unique id) in an array and use that to delete it later?

Q: Does that still work after packaging / patching? ( actually don’t know )…

ill test the proposed solutions later and will let you know during packaging. Currently there seems to be 2 solutions working (saving names and level) and clockwork solution using ids. I think the id solution seems to be more memory efficient.

Save and loading with my solution based on actor names and associated level name works great in packaged project.

Will test ID later.

1 Like

save the game instance variables :slight_smile:

Yes, true, but why use two systems instead of one?..

I know this is years old and I hope everyone is doing well. I’m trying to implement this in my project and it works fine. Only when I start a new game I get a bunch of index errors

I’m trying to come up with a method where the begin play code only runs on load save and was hoping someone might have some suggestions? Sorry to re-activate such an old post…

Thanks

@Ewl400

Add a test to see if the array is not empty and has at least 1 entry.

if (!Level1Pickups.IsEmpty() && Level1Pickups.Num() > 0) {
	/// your code here
}