This question was created in reference to: [SoftObjectPtr, LazyObjectPtr, [Content removed]
Hello,
we needed some persistent ID for actors in the game (to allow actors to reference each other, and to reference them in save games). I have tried using softObjectPtrs, but they don’t always work (in Level instances), and change constantly between editor/pie/cooked game. Also, SoftObjectPtrs can change between game versions (just moving the actor across WP grid boundary changes resulting SoftObjectPath).
For this reason we have decided to use a guid for each actor. This guid is generated once when the actor is created and stays persistent when modifying the actor in any way, during pie duplication and during cooking (this means that during pie, there are two actors with same id, one in each world. Which is fine, as we consider the "g"uid unique only per-world).
The great thing is, there is already one guid in Unreal, the ActorInstance guid, and it works fine, it is even correctly resolved when in a LevelInstace, by combining actor guid and LeveInstaceActor guid. So I have basically just moved some #ifdefs around and added serialization, and we use the ActorInstanceGuid on the actor itself.
So far it seems that it works fine. Is there are good reason not to do this? I have for example already found a very weird behavior with Replace Actors feature, which for a brief moment spawns another actor with the same guid. It is possible there are simillar hidden issues somewhere in the editor that we haven’t found yet. And if this is not a good solution, then what is the alternative? Needing to identify actors is surely common to many projects, is there already a solution that we missed?
Hi Martin,
ActorGuid is probably what you want. But as you noticed, it’s locked away behind a WITH_EDITORONLY_DATA guard, so shuffling code around is necessary.
In the event you don’t want to maintain an engine mod, you can roll this system yourself (although, it’s a little more long-winded to do).
Assuming you have some sort of AMyActorBase/AMyCharacterBase classes, you can put a GUID there with the same UPROPERTIES as ActorGuid has. In the OnConstruction() function, check if the GUID is valid, and if not assign a new one. This will get serialized for placed actors so the next time they are loaded and the construction function runs, the GUID will be valid and not get reassigned. If you add this with existing levels and existing actors, those levels would need to be touched and resaved to get the GUIDs written out. Since you would likely have to duplicate this code for several classes, it’s less ideal than an engine mod (but if you were using the binary install of the engine, this is your only option), but it’s an alternative nonetheless.
One thing to keep in mind is if you dynamically spawn actors at runtime, they will get a GUID assigned when they are spawned. If you are keeping references to these GUIDs between other actors or systems, when you respawn the actor you’ll want to make sure to reassign its old GUID, since the newly respawned actor will get a new different GUID.
Regarding the duplicate GUIDs in PIE; this is due to the ActorGuid’s UPROPERTY NonPIEDuplicateTransient and is intentional. The DuplicateTransient part ensures that when an actor is duplicated, that particular UPROERTY is _not_ duplicated (so the duplicated actor will get a new GUID). The NonPIE part excludes this behavior from PIE so that the actors “in game” keep the GUIDs they were assigned “in editor”.
Hope this information is of some help!