Hey! Sorry for the late reply!
Its been a while since this post, so I’ve had a lot of different experiences now with things not saving in packaged games.
Here are a couple of them that I can remember at the top of my head.
-
I have heard that using delay can sometimes create little hiccups in the system? Like if you use delays wrong and suddenly something fires off at the same time as something else and therefore overwrites the event you actually want?
-
As for your question about if I know of any tutorials about saving destroyed actors, I don’t know much of any other than the ones I linked before.
My understanding so far of saving deleted actors though is this: You can either choose to save each time the actors are destroyed, or you can choose to save only the remaining actors on the map. I prefer to use the second option as it seems to be the easiest for me to remember though.
So say that we do the second option: Scenario is you have a lot of items in a level that you only want the player to be able to pick up once and never again. So the player picks it up, relogs the game and the item should no longer be there.
What you can do is when you save via a pause screen for example, is make a save event where you use “get all actors of class” and run it through a “for each loop”. Via the “for each loop” pin, you get all the information you want to store.
- Get class → saves the item’s class
- Get transform → saves the item’s location
And so on.
Now where do you store this information in the save game? You store all the actors information via an array struct. Inside the struct, you want to have a pin for the information you want to store, so one for “class” and one for "transform.
It should look something like this:
(we clear the array every time so that we don’t get duplicates)
To load what you destroyed (items you have already picked up), you would first want to delete every item in the world by using “get all actors of class” running that into a “for each loop” and using “destroy actor”.
Then you want to spawn only the actors that remained (aka the info we stored in that array). Your set up would look something like this:
Now if there are things that have been “half destroyed” in the world, for example trees have been cut but the trunk still remains, you could have a bool variable in your tree blueprint that says “broken”. And set the value to true once the desired part of the tree has been cut. To save that for when you load the game you would just add another pin to your struct thats a bool, and hook it up like you did with the transform and class.
This method seems like the best one for most/if not all my saving cases so far. Yes, using “get all actors of class” is heavier the more actors you have on the map, but I havent really seen much of a performance hit myself when saving up to 5k actors at once.
Hope that makes sense!
- Using string = string seems to be tricky sometimes for packaged games to understand. The nodes work perfectly, but where I had an issue was when I was comparing something like a variable with an item name (A) to a self written name (B). The issue here was that when I wanted to have the following branch to read TRUE, it would always go false in packaged games because of one silly thing. Using capital letter.
Heres an image to show what I mean:
That setup would work perfectly in the editor, but my experience as of now (I’m using 5.1) , is that when its packaged, it reads the “Weapon” wrong. Its reading A as “weapon” not “Weapon”, (without the capital letter). To summarize, when it comes to using string = string like that, I would advice to never make IDs with capital letters. To debug this, I just packaged the game with a development build and hooked up a print string to the output of the string I’m comparing the value with, to see what it prints, and thats how I found out that it changes the variable to a name without capital letters.
Now I don’t know if this could be applied to persistent player IDs too, but its a good thing to keep in mind I guess?
And for your question about persistent player ID, I am still as of now 100% sure how this works or the logic for it, but if you take the word “persistent” you can think of the word “static”. It NEVER changes. It stays the same.
So when you look at something like the node “get player controller” you will notice that the input pin says “0”. Thats because the default persistent ID I believe, of the player is “0”. So if you have a single player game you wouldnt have to worry about this, but I would assume that if you have a multiplayer game you need to make an ID for each player, like “player 1”, “player 2” etc. or find an ID that is the same (like how steam lets players have usernames and so forth). I wouldn’t take my word for it 100% though, but maybe this can help you look up more about it? And anyone else who knows more, please correct me if I’m wrong and add more information. I would love to know more about it too.
- It might be obvious, but ill mention it either way for new devs! If you use streaming levels, you would not want actors that you want to save, to be a part of a streaming level. They should be in persistent level since they need to be loaded when you load the game. Actors that are a part of streaming levels will not save, (because they load and unload whenever players enter certain areas on the map)
I can’t remember much else at this time, but these are some of the things I’ve learned the past few months