I'm hitting a wall with saving and loading persistent data in Unreal Engine, especially with references that become invalid.

Got it :smiley:
its finally working:

//SAVING:
void AUnitManager::SaveData_Implementation(UMySaveGame* SaveGameRef)
{
	if (!IsValid(SaveGameRef))
		return;

    SaveGameRef->SerializedUnitActors.Empty();

    for (AMyUnitActor* Unit : All_UnitActors)
    {
        if (!IsValid(Unit)) continue;

        FSerializedActorData Entry;
        //Entry.ActorClass = Unit->GetClass();
        Entry.SavedName = Unit->GetPathName();

        Entry.ActorClass = Unit->GetClass();
        Entry.ActorPath = Unit->GetPathName();

        Entry.ReferencePathName1 = Unit->CurrentRegion->GetPathName();

        FMemoryWriter Writer(Entry.Data, true);
        FObjectAndNameAsStringProxyArchive Ar(Writer, false);
        Ar.ArIsSaveGame = true;
        Unit->Serialize(Ar);

        SaveGameRef->SerializedUnitActors.Add(Entry);
    }

    SaveGameRef->SerializedRegions.Empty();


    for (AMyRegionActor* Region : All_RegionActors)
    {
        if (!IsValid(Region)) continue;

        FSerializedActorData Entry;
        //Entry.ActorClass = Unit->GetClass();
        Entry.SavedName = Region->GetPathName();

        Entry.ActorClass = Region->GetClass();
        Entry.ActorPath = Region->GetPathName();

        Entry.ReferencePathName1 = Region->CurrentUnit->GetPathName();

        FMemoryWriter Writer(Entry.Data, true);
        FObjectAndNameAsStringProxyArchive Ar(Writer, false);
        Ar.ArIsSaveGame = true;
        Region->Serialize(Ar);

        SaveGameRef->SerializedRegions.Add(Entry);
    }
}


//LOADING:
   for (const FSerializedActorData& LoadedData : SaveGameRef->SerializedUnitActors)
    {
        AActor* CurrentActor = UGameplayStatics::BeginDeferredActorSpawnFromClass(this, LoadedData.ActorClass, FTransform(), ESpawnActorCollisionHandlingMethod::AlwaysSpawn);

        CurrentActor->FinishSpawning(FTransform());

        FString IDName;// old actor path (old reference)

        LoadedData.ActorPath.Split(".", nullptr, &IDName, ESearchCase::IgnoreCase, ESearchDir::FromEnd);
        CurrentActor->Rename(*IDName);
        All_UnitActors.Add(Cast<AMyUnitActor>(CurrentActor));
    }

    // Spawn Regions
    for (const FSerializedActorData& LoadedData : SaveGameRef->SerializedRegions)
    {
        AActor* CurrentActor = UGameplayStatics::BeginDeferredActorSpawnFromClass(this, LoadedData.ActorClass, FTransform(), ESpawnActorCollisionHandlingMethod::AlwaysSpawn);

        CurrentActor->FinishSpawning(FTransform());

        FString IDName;// old actor path (old reference)

        LoadedData.ActorPath.Split(".", nullptr, &IDName, ESearchCase::IgnoreCase, ESearchDir::FromEnd);
        CurrentActor->Rename(*IDName);
        All_RegionActors.Add(Cast<AMyRegionActor>(CurrentActor));

    }

    // === PASS 2 - DESERIALIZE ===

    // Deserialize Units
    for (int32 i = 0; i < SaveGameRef->SerializedUnitActors.Num(); ++i)
    {
        FMemoryReader Reader(SaveGameRef->SerializedUnitActors[i].Data, true);
        FObjectAndNameAsStringProxyArchive Ar(Reader, true);
        Ar.ArIsSaveGame = true;

        All_UnitActors[i]->Serialize(Ar);
    }

    // Deserialize Regions
    for (int32 i = 0; i < SaveGameRef->SerializedRegions.Num(); ++i)
    {
        FMemoryReader Reader(SaveGameRef->SerializedRegions[i].Data, true);
        FObjectAndNameAsStringProxyArchive Ar(Reader, true);
        Ar.ArIsSaveGame = true;

        All_RegionActors[i]->Serialize(Ar);
    }

This is the best solution. It will save me a ton of work, because now i dont have to reconnect every single actor reference using a FGuid. Just the GetPathName() works :flexed_biceps:
I already debugged it and its fixing the references. Amazing.
Thanks @Auran13 , @PREDALIEN

2 Likes