My brain is absolutely fried trying to figure out how to make this work. I have BP actors that get spawned in when their pickup blueprint gets interacted with. When that Actor spawns in the player’s hands, it also gets added to an “inventory” system (player can’t interact with it other than scroll through it) in the actor component where it’s just a class variable array referencing the Base BP for the actors, plugged into an add unique class array.
I want these actors to survive level transitions but they end up getting canned with the game instance every time. Test Integers and names survive though. I Did some digging and came to the conclusion that game instances hate actors and any references to them, even if they’re in structs. If you want actors to survive level transitions, you have to forfeit blueprinting and go the C++ route, which I’d prefer not to. Save game on the other hand seems like it would remedy this issue, but it’s not considered the best route to take for optimization when doing level transitions. Save game before loading level and then load save on begin play in the next level.
Part of me believes I’m just setting up my inventory wrong from the get go. But I’m open to any suggestions on how to go about tackling this.
As a general rule, Actors do not survive level transitions*. It doesn’t matter if they are reference by the game instance because they are “owned” by the World and the World is being destroyed which forces the actors to be destroyed as well.
Creating a save game is a perfectly viable solution to this transition issue. The trick can be that you don’t actually write it to disk. You create it and fill it in (the same as when making a save in the middle of gameplay) but then you just keep a reference to it on the game instance. Because a save game is a UObject and not an Actor it should transition just fine (as long a you don’t outer it to something in the World that gets destroyed). Then when you get to the next level you apply that data similarly to loading a save game.
It’s not exactly the same, there are things that do have to handle a little different because you might have things you setup when first entering the level that should happen on the transition but now when loading a save (because the save would already have that data)
Depending on the data you need to persist, you could also have a completely unique “save data” that you only use for transitions. The convenient part of using the save games is that you sort of continually test your save games with normal gameplay. At least for as much as the travel and manual processes overlap.
*There is a thing called Seamless Travel that allows the game to “travel” actors from one world to the next. However it can have some issues in PIE and can be fiddly.
This definitely sheds some light on my dilemma. I’ll try and test this out later in the day when I have more free time. At most, I only have around 8 actors with data assets right now that I care about making it to the next levels. If I build a save game function strictly for handling level transitions, is there a possibility that this could corrupt if I have another save game set for just progress in general? I may be overthinking it but I just want to make sure I’m covering all my bases. I appreciate the responses in advance.
Maybe, I’m not sure what you mean exactly. If you have the same code trying to support both, then you could definitely have one use case cause an unintended effect on the other.
Conversely if you have separate code for each use case you’ll likely have more duplicated code than you want.
When I’ve done this, the transition save has been identical to the progress save, except with a flag that identifies it as a transition save. As in I could read and write the save to disk and it would work exactly the same as reading a progress save.
It took me a little longer than expected to get back to blueprinting and try making a save game. I got one set up but for some reason I’m getting errored at my save game struct. The blueprint interface event that has the same struct node on it is getting the exact data I want, but the moment it goes to the game instance and feeds into a set node for the same struct coming from the save game variable, it just comes back as none.
I’m at a loss as to why the struct in the save game blueprint refuses to acknowledge any incoming data.
Well now I’m going to sound like a fool, but I just now figured out my problem to that. It was coming back null because I had my save and load events backwards that was causing the null in the save game variable.
I got my current held actor to survive a level transition now but I’m still missing the rest of the inventory and I got to figure out a way to keep the actor persistent even after I play and quit the editor twice or more.
I’m going to keep re-reading MagForceSeven’s first comment over and over like a broken record and hope I’ll crack the code in the next day or two. If not, I’ll be back with an update on my current situation.
Are the inactive items in your inventory also actors? If so, you should probably change the inventory system to only store the item name (plus quantity. and durability/ammo/whaevs as needed), then spawn new actors when used. As for held weapons, it might be worth changing them over to being a scene component on the characters, and have it so equipping item from bag just calls a func on the comp to change the mesh and stuff. Since actor components travel with the parent, going to another level might be less painful this way. Granted, this makes dropping them trickier, since you’d need to spawn a new pickup actor. But at least dropped actors wouldn’t need to travel too.
Yes, the inventory setup consists of actor classes. I actually managed to make my inventory system persist now without issues via soft class references. I made a Cache inventory and a normal inventory system in my actor component (Cache being the soft reference and normal being the hard reference). When the weapon is picked up, the soft reference instantly goes into the cache inventory and then it gets resolved into the normal inventory where it then gets spawned and attached to the actor. Every time I quit or teleport to different levels, the cache inventory persists in the game instance and then gets called back in on event begin play where it then gets resolved back into its hard reference. The current weapon not loading back after quitting was an override issue. I just had to put a delay until next tick on the teleporter.
I don’t know if this is the best way to go about doing it, but for something that’s only going to call in 4 actors max, this’ll do the trick for now. All the info on all the weapons are in their own respective Data Asset. Luckily I don’t plan on adding drops for this one either so we’re good there.
I appreciate you taking time out of your day to comment a possible solution though.