Help 4.23 Broke my Save/Load System On A Packaged Build

Hey guys, I really need some help.

I have a C++ Save System that I made, and it has worked since a very long time, no problems.
But since I updated my project to 4.23, the system broke.

I’m trying for over a day to find out whats going on and I just can’t.

I have a few suspicions but I’m not sure, I’ll first explain how my save system works then my suspicions.

First, I save the relevant actors references within an Array (and more information within ActorRecords, not relevant for this case)

After this, I open a new level, start it and make that level load the relevant save file… ok, it works just fine up until this point.

Next, I compare every actor reference from the array to the ones in the level, deleting the ones that are not found within the array (dead enemies, picked up or used items, etc…) and creating actors from the array that were not found within the level (spawned enemies during runtime, etc…)

Then I load their ActorRecords and etc…

So, whats the issue?

Before 4.23, the game used to match the references saved within the array to the ones in the level, so for example: PlayerCharacter wouldn’t get deleted because he would exist both in the array and in the level, matching them perfectly and updating their values (works just fine on the 4.23 editor, and in previous versions’ compiled builds), see the log here as an example:

[SPOILER]Purges actors without reference in the Array but that are present in the Level.
[2019.09.19-06.17.44:464][102]LoadGameLog: Display: BP_WeaponSpawn3_53 has no loading reference, purging it…
[2019.09.19-06.17.44:464][102]LoadGameLog: Display: BP_WeaponSpawn4 has no loading reference, purging it…

Creates actors which references were found in the loaded Array but not in the Level.
[2019.09.19-06.17.44:484][102]LoadGameLog: Warning: Creating Actor Base_Spear01_C_2 of class Base_Spear01_C.
[2019.09.19-06.17.44:485][102]LoadGameLog: Warning: Creating Actor Base_Spear01_C_3 of class Base_Spear01_C.

Loads player successfully.
[2019.09.19-06.17.44:485][102]LoadGameLog: Loading actor PlayerCharacter_C_0…
[2019.09.19-06.17.44:486][102]LoadGameLog: Warning: PlayerCharacter_C_0 has 0 spells.
[2019.09.19-06.17.44:486][102]LoadGameLog: Warning: PlayerCharacter_C_0 has 0 items.[/SPOILER]

Now, within the compiled build of 4.23, the PlayerCharacter is getting purged because the reference inside the level does not match the reference inside the Array, then the reference inside the array is also created, like this:

[SPOILER]Player inside the level gets deleted because it doesn’t match the reference in the Array
[2019.09.19-06.26.35:765][871]LoadGameLog: Display: PlayerCharacter_C_2147481494 has no loading reference, purging it…

Player gets recreated because the array reference is not found within the level.
[2019.09.19-06.26.35:766][871]LoadGameLog: Warning: Creating Actor PlayerCharacter_C_2147482312 of class PlayerCharacter_C.

Player fails to load.[/SPOILER]

Note how in the first log, the player character is named PlayerCharacter_C_0, with “PlayerCharacter” being my blueprint’s name.
In the second log, which fails, the PlayerCharacter has this gigantic number after his name PlayerCharacter_C_2147481494 and the other PlayerCharacter_C_2147482312

I suspect UE4 changed something related to this or the GC is now clearing the references within my Array, neither of which helps me deal with this issue.

I hope anyone can help me, its extremely complicated to explain how everything works and I’m willing to share more details as necessary, I didn’t provide code snippets because it is quite huge and would make this post even bigger and harder to explain.

You should generate a GUID for items and use that as an identifier, as references have never been guaranteed to be stable anyways. I basically made a component that generates a GUID and stores it, and I have an editor module that will set a GUID when dragging an actor in.

Thanks for replying man !!

Can you give me an starting point as to how I would go about generating an unique GUID for each Actor??

I have some thoughts, but maybe you have a simpler system that I would be able to create

Epic is attaching this ID prefix on actors after 4.23, apparently they did this thing for Fortnite trying to stop memory scanners from mapping entity IDs… They didn’t ask anyone if that would be a good idea or if there’s any way to disable it.

Yeap, now my Save System is broken and I can’t fix it.

Tried 4 different ways now, no success. I have many actors to save, too many. It was working perfectly before 4.23, now everything is broken.

I feel really down by it, its not like making the Save System was easy the first time around, having to redo it and no other idea of how to do it is just frustrating.

I hope anyone finds a solution for this in the future, or that Epic themselves revert this change or give us an option to keep using the previous iteration, for now I went back to 4.22.

Couldn’t possibly find a way around, got frustred from trying and decided to go back.

My game just can’t exist without a Save System.

I would also be interested in seeing how you did this.

Here you go (be warned this is the worst code in my whole game so I do a couple things poorly. Also be warned that if you preview your GUID in editor it won’t appear correct because of a bug.

  1. Make an editor module. Here is MyGameEditor.cpp:


#include "MyGameEditor.h"
#include "Editor.h"
#include "SaveComponent.h"
void FMyGameEditorModule::StartupModule() { ActorDragged = FEditorDelegates::OnNewActorsDropped.AddRaw(this, &FMyGameEditorModule::OnActorDragged); }

void FMyGameEditorModule::ShutdownModule() { FEditorDelegates::OnNewActorsDropped.Remove(ActorDragged); }

void FMyGameEditorModule::OnActorDragged(const TArray<UObject*>& Objects, const TArray<AActor*>& Actors) {
    for (auto actor : Actors) {
        if (auto saveComponent = actor->FindComponentByClass<USaveComponent>()) {
            saveComponent->CheckGuid();
        }
    }
}

IMPLEMENT_PRIMARY_GAME_MODULE(FMyGameEditorModule, MyGameEditor, "MyGameEditor");


  1. Make a save component that you attach to your saveable Actors. Here is my SaveComponent.cpp:


#include "SaveComponent.h"
#include "Kismet/GameplayStatics.h"

USaveComponent::USaveComponent() {
    PrimaryComponentTick.bCanEverTick = false;
#if WITH_EDITOR
    UBlueprint* blueprint = Cast<UBlueprint>(GetClass()->ClassGeneratedBy);
    if (blueprint) blueprint->bRunConstructionScriptOnDrag = false;
#endif
}

void USaveComponent::BeginPlay() {
    Super::BeginPlay();
    CheckGuid();
}

#if WITH_EDITOR
// Handles regenerating when you duplicate
void USaveComponent::PostEditImport() {
    Super::PostEditImport();

    RegenerateGuid();
}
#endif

void USaveComponent::CheckGuid() {
    auto def = FGuid{};
    if (Guid == def) { RegenerateGuid(); }
}

void USaveComponent::RegenerateGuid() {
    FGuid newGuid = FGuid::NewGuid();

    // This might actually work without doing it element-wise, not sure and didn't feel like testing after messing with this code for a whole day
    Guid.A = newGuid.A;
    Guid.B = newGuid.B;
    Guid.C = newGuid.C;
    Guid.D = newGuid.D;
}


Thanks for sharing this, but how do you address actors created at runtime, for example?

Since they will have the SaveComponent attached, when the component’s constructor is run, it will generate a GUID. It will be a different GUID every time, so really those actors will just be deleted and spawned with the right parameters deserialized into them again with the way my code works right now.

How did you downgrade your project, I can’t seem to get into it without the engine telling me that its the wrong version!

Whenever I update my project to a new engine version, I keep a backup of the previous one just in case…

All I had to do was to open the previous version and work on it.

Didn’t lose much progress since all my time was wasted trying to fix the save system…

Which by the way, I didn’t find a good solution for… I wish an UE4 dev would read this and provide us with the option of reverting this feature in 4.23

I’ve been sharing this thread where i can so i hope that can bring some attention to this!

Thanks, that should help getting more attention to the matter, I’ll see if I can share on reddit later today.

Bump, this issue remains and I still need the help, if possible

I really believe you guys need to just use the code I posted here. That took me like a week to whip, and I just gave it away for free, but you guys are STILL asking for help directly from Epic Games themselves. Epic is not going to revert a change like this. It’s not a bug. There was no stability guarantee on the IDs you guys were using in the first place. You should have had a unique ID system like everyone else has planned for, just like I gave you right here. Yeah, it might take a whole hour for you to get working considering you need to make an engine module. That’s really not a lot of time considering a save system is a pretty core feature, and it literally took me a week as I already stated. I’m not opposed to you [em]not[/em] using my code either; you’ll just have to write your own ID storing system yourselves.

I’m seriously not trying to be condescending but it’s a little disappointing when I go super out of my way to help someone and they are clearly just too lazy to even copy and paste the code I made into their own codebase and make some very slight changes to solve all their issues. After about a year of using Unreal, I’m no veteran, but I can at least tell you this: it is very time consuming, and you will absolutely have times where you need to dedicate a whole day or a whole week to something as “stupid” as saving your game because there is no easy solution you can find. In this case, you just had someone deliver it to you on a silver platter, but you’re asking Epic to change something in the engine that they had to change for their multi-million dollar IP. Seriously not trying to flame here…clearly I care and have tried to be nice; that’s the reason I went so far as to provide working source code from my game for you guys! Just venting because I see a lot of these type of posts on here and most of the time I just ignore them altogether. Thought I would give it a shot and help out for once, but of course, my working advice is ignored outright and met with complaints that the game engine itself should be changed. There are so many things Epic has to do that are literal bugs in the engine that could be fixed instead of adding a toggle to revert back to the old behavior of having slightly-stable IDs for things, but here we are, yet again, with people begging for a solution to avoid a slight amount of work, even after one was already presented.

Do we know if these unique actor IDs came into 4.24.x?

In my systems I create my own IDs now so I don’t know, but I bet the situation is the same.