Save game question with generated Identifiers

I am having the following problem to solve.

First of all, I am using a plugin from the marketplace that is very useful, but I can not solve this problem, so I would like to understand how to solve the problem without the plugin, and then understand what I am doing wrong with it.
I talked with the plugins creator, who is very responsive, but I prefer to open the question so as not to overwhelm the plugin creator with even more questions.

How can I save (save game) information about actors (spawned or not), and then get the saved status at the time of load game.

Example:
The player pick up an item, This item should disappear forever.

So a simple solution is to keep a list/map of identifiers for those items and save a boolean when the item is saved. When Load the game, simply hide or destroy the item based on that list/map.
Now for this to work I need to generate a mechanism to obtain a unique identifier (a GUID i.e.) for each Actor…
The problem comes when this mechanism must work at runtime, so a new unique identifier is generated, different from the first one. Therefore, the list becomes obsolete.
So now I have the problem in that I must save the generated identifier

1) How do you solve this problem?

2) Now supposing that this problem is solved, how can I make it work at multiple levels as well?
(I understand that if the identifier is unique, I can use the same list for all levels)

**3) Should I have something in mind or be careful when I work with streamed sub levels?

  1. and finally, Maybe I am overthinking a very easy to solve problem??**

thanks to lot!

I use the AssetManager to load various actors. So I just save a list of FPrimaryAssetId or the strings necessary to construct one. This way not only can I identify an object, I can directly pass the id to the asset manager to load it from storage.

Assign new FGuid in construction script. (Assign new one in PostEditImport if you want to support alt-drag copying in editor.) Use this guid to save state of object in save game. When loading map (or sublevel) read the saved state for that guid back into object.

Thanks both for the responses!

Ok I will try this method, which is something similar to the one mentioned above.
I’m not sure if the generated GUID will remain unchanged when moving an actor across the map in edit mode, but I’ll try

EDIT: so yes, every time I move the actor ir changes the identifier (created in the construction script).
…well, actually the editor changes the identifier all the time.
This is a problem because after a game release you cant move anything from map because you will break the existing save games.

Is there a way to avoid this? I mean it should be a way or other production games could not have save game feature.

Yes - sorry - in construction script only create new if not equal to 0

well, now I feel stupid.
Thanks a lot!

“Create a new if equal to 0” I guess

The only problem with this is that the constructor will run in the editor, causing the GUID not to be default any more, so when you make another instance, it won’t know to regenerate it.

Just keep invalidated the one that is in Blueprint’s asset (Default Object). So all instances generate their own.

The problem is that if I set it in the constructor, the constructor seemed to be running in the editor as well, regenerating the invalidated one. I solved this by creating an editor module and having the editor module generate a GUID OnDrop. I also overrode the PostEditImport func in my save component so if something is duplicated, a new one is generated there as well.

In Constructor you can check if a class is default object.
If has default object flag = don’t generate guid.

How would I go about doing that? I can’t find anything after a search. (Maybe if I was at the computer right now Intellisense would pop up with something, but it’s helpful just for others in the future looking at this thread to know what to do too)

Edit: Took me two seconds to find with VS. I believe this code should work (haven’t tested):


if (HasAnyFlags(EObjectFlags::RF_ClassDefaultObject)) {
    // Don't generate GUID
} else if (Guid == FGuid{}) {
    Guid = FGuid::NewGuid();
}

Edit 2:

This will not regenerate the GUID when you duplicate an object though, which will be a problem. Unfortunately, the DuplicateTransient UPROPERTY is still broken, so you can’t use that. You have to overload PostEditImport and force it to generate a new GUID when it’s called.

1 Like

Could go into more detail please?

  • Which OnDrop did you use?
  • Save component: Do you mean in an UActorComponent class? I did not find such an event there but I’d like to avoid using actor components just for saving anyway.

In my limited time I’m failed to generate guids in editor at spawn time, so i’m ended up with EditorUtilityWidget that gather all required actors on current level, set them a new guid if it’s invalid and save all the changed files.

as for this:

2) Now supposing that this problem is solved, how can I make it work at multiple levels as well?

In my USaveGame object i’m going to have a TArray<FGuid> of guids that player already interacted with. As you said - since guids are unique, it doesn’t matter which level did the belong to