[PLUGIN] Savior

I will push an update for 4.27 and UE5 where the StaticSlot is marked Blueprint Read-Only, so you can do this on your blueprints that are destroyed when traveling across levels happens while loading slot data:


That way you will always be notified, regardless of the original blueprint where Load Game World [+Callbacks] was executed was destroyed or not.

I really load another level when loading, unlike the one that is currently open. As I understand it, it is better to place Bind Event either in GameMode or GameInstance?
Thank you for your work.

When a new map is open, everything from previous persistent map is destroyed, except for the Game Instance that remains alive until the game is closed.

Hi Bruno,

I have updated your plugin to version 3.9.5 in UE4.27.2, and both the [SAVIOR] Load Game World (Async) and [SAVIOR] Load Game World [+Callbacks] nodes appear to be broken, on our end at least.

I can not load in my level save-data as it crashes on a delegate callback event. (Probably trying to execute an event that is not bound) Could you please verify that they are broken or help us out to find out what the culprit is?

I have looked through some of the code from our previously used version 3.9.3 (which works perfectly) and compared it the most recent 3.9.5 version, and I see a lot of changes have been made in the plugin. (i.e; Savior3 renamed entirely to Savior) and the contents of the LoadGameWorld functions inside both SaviorAsync.cpp and Savior.cpp have changed dramatically, not sure why they have had to be changed since the 3.9.3 methods looked more stable.

Please let me know if the description is unclear or you need additional information.

Thank you :slight_smile:

Edit: Additional findings:

  • Trying to load data from for instance Level_Menu to Level_Game (with ResetLevelOnLoad either true or false) crashes the application.
  • Trying to load data from for instance Level_Game to Level_Game (with ResetLevelOnLoad set to true) crashes the application.
  • Trying to load data from for instance Level_Game to Level_Game (with ResetLevelOnLoad set to false) does NOT crash the application.

(so basically any time the level resets / the application decides to travel to another level crashes the game? :open_mouth: )

Please email me the crash logs.
(I mean crash logs, not Play in Editor logs)


I can also give you a link to 3.9.3 if that version works best for you.

I’ve sent you an email. :slight_smile:

I have reverted back to 3.9.3 for now, I have had it backed-up before upgrading.

Thank you for your time! :smiley:

“[SAVIOR]: Invalid Target Slot.”

Means the source slot class passed to the node is null.
I bet this is because the type renamed from USavior3 to USavior object.
Probably recreating your slot classes on asset browser would fix it when updating to latest version.


The types should never have a number suffix, I was forced to do it back then because of versioning problems in the Marketplace while several projects were still using Savior 2.

The last v3 on UE4.27 is the same version of plugin for Unreal 5, so there’s no “3” suffix after classes anymore.

I think for whatever reason the engine failed to redirect your slot classes from “Savior3” to “Savior” assets, and this crash happened. The code where the crash log points didn’t really change, your Blueprint should not compile when “[SAVIOR]: Invalid Target Slot.” assertion happens, but I think because the problem with redirector mentioned above, somehow it compiles… It’s important to “refresh all nodes” of the blueprint when changes like that is implemented.

Thanks for your reply!

I have done the following, however, the problem still persists:

  • Refreshed all blueprint nodes that have any linkage with the Savior system.
  • Deleted all “old” Savior Slot files
  • Applied the fix-all-redirectors clean up in-engine several times
  • Rebooted the engine several times
  • Created a new Save Slot and linked that to my saving system

What I found out is that my custom BP_SaveManager (which is a BP that I’ve built to not die or gets cleaned up / garbage collected across level changing) is not able to execute the Load Game World (Async) (and the +Callbacks) nodes.

However, if I were to put the Load nodes inside one of my Level Blueprints (where it should ideally not be placed in my particular project), the node does fire. To add to this, both the Callbacks, and the On Success / On Fail output pins do not get fired.

Tricky situation :thinking:

You don’t really need to use that by the way.
There is a persistent Static Slot object spawned by the Savior Subsystem which is attached to your Game Instance as soon the game is launched and it never dies until the game is closed. See posts above:


With C++ you can push any data to the StaticSlot and load from any level.
It’s what the nodes you use actually do.

Hi Bruno,

Thanks for your replies. Some of the issues have been resolved so far.
However, we have one issue (for a while now) that keeps bugging us and we have no way to figure out how to fix it.

We are creating an archviz software platform which contain a lot of items per each level. However, every now and then (quite frequently actually, and even more so exponentially with more items that we wish to save) our application crashes whenever we want to save our level.

We are not sure if its an issue caused by the plugin or by the engine itself because the logs are quite hard to understand on memory level. Each time crashing to another crash stack log, but always pointing toward the same direction: memory.

The crash always seem to originate from trying to save FMaterialRecords. A small crash stack log can be found below. Please let me know if this issue sounds familiar or you require additional feedback / crash-logs to determine the cause of the issue.

Thanks!

<unknown> 0x00007ff911c5146c
[Inlined] FGenericPlatformMemory::Memcpy(void *,const void *,unsigned long long) GenericPlatformMemory.h:532
[Inlined] FMemory::Memcpy(void *,const void *,unsigned long long) UnrealMemory.h:143
[Inlined] TSparseArray<TSetElement<TTuple<FGuid,FMatScalarRecord> >,TSparseArrayAllocator<TSizedDefaultAllocator<32>,FDefaultBitArrayAllocator> >::operator=(const TSparseArray<TSetElement<TTuple<FGuid,FMatScalarRecord> >,TSparseArrayAllocator<TSizedDefaultAllocator<32>,FDefaultBitArrayAllocator> > &) SparseArray.h:758
TSet<TTuple<FGuid,FMatScalarRecord>,TDefaultMapHashableKeyFuncs<FGuid,FMatScalarRecord,0>,FDefaultSetAllocator>::operator=(const TSet<TTuple<FGuid,FMatScalarRecord>,TDefaultMapHashableKeyFuncs<FGuid,FMatScalarRecord,0>,FDefaultSetAllocator> &) Set.h:345
[Inlined] TSet<TTuple<FGuid,FMatScalarRecord>,TDefaultMapHashableKeyFuncs<FGuid,FMatScalarRecord,0>,FDefaultSetAllocator>::{ctor}(const TSet<TTuple<FGuid,FMatScalarRecord>,TDefaultMapHashableKeyFuncs<FGuid,FMatScalarRecord,0>,FDefaultSetAllocator> &) Set.h:312
[Inlined] TMapBase<FGuid,FMatScalarRecord,FDefaultSetAllocator,TDefaultMapHashableKeyFuncs<FGuid,FMatScalarRecord,0> >::{ctor}(const TMapBase<FGuid,FMatScalarRecord,FDefaultSetAllocator,TDefaultMapHashableKeyFuncs<FGuid,FMatScalarRecord,0> > &) 0x00007ff7d0ea09aa
[Inlined] TSortableMapBase<FGuid,FMatScalarRecord,FDefaultSetAllocator,TDefaultMapHashableKeyFuncs<FGuid,FMatScalarRecord,0> >::{ctor}(const TSortableMapBase<FGuid,FMatScalarRecord,FDefaultSetAllocator,TDefaultMapHashableKeyFuncs<FGuid,FMatScalarRecord,0> > &) 0x00007ff7d0ea09aa
[Inlined] TMap<FGuid,FMatScalarRecord,FDefaultSetAllocator,TDefaultMapHashableKeyFuncs<FGuid,FMatScalarRecord,0> >::{ctor}(const TMap<FGuid,FMatScalarRecord,FDefaultSetAllocator,TDefaultMapHashableKeyFuncs<FGuid,FMatScalarRecord,0> > &) 0x00007ff7d0ea09aa
FMaterialRecord::FMaterialRecord(const FMaterialRecord &) 0x00007ff7d0ea09aa
[Inlined] UE4Tuple_Private::TTupleBaseElement<FMaterialRecord,1,2>::{ctor}(const UE4Tuple_Private::TTupleBaseElement<FMaterialRecord,1,2> &) 0x00007ff7d0ea56d6
[Inlined] UE4Tuple_Private::TTupleBase<TIntegerSequence<unsigned int,0,1>,FName,FMaterialRecord>::{ctor}(const UE4Tuple_Private::TTupleBase<TIntegerSequence<unsigned int,0,1>,FName,FMaterialRecord> &) 0x00007ff7d0ea56d1
[Inlined] TTuple<FName,FMaterialRecord>::{ctor}(const TTuple<FName,FMaterialRecord> &) 0x00007ff7d0ea56c1
[Inlined] TSetElementBase<TTuple<FName,FMaterialRecord>,1>::{ctor}(const TSetElementBase<TTuple<FName,FMaterialRecord>,1> &) 0x00007ff7d0ea56c1
[Inlined] TSetElement<TTuple<FName,FMaterialRecord> >::{ctor}(const TSetElement<TTuple<FName,FMaterialRecord> > &) 0x00007ff7d0ea56c1
[Inlined] TSparseArray<TSetElement<TTuple<FName,FMaterialRecord> >,TSparseArrayAllocator<TSizedDefaultAllocator<32>,FDefaultBitArrayAllocator> >::operator=(const TSparseArray<TSetElement<TTuple<FName,FMaterialRecord> >,TSparseArrayAllocator<TSizedDefaultAllocator<32>,FDefaultBitArrayAllocator> > &) SparseArray.h:746
TSet<TTuple<FName,FMaterialRecord>,TDefaultMapHashableKeyFuncs<FName,FMaterialRecord,0>,FDefaultSetAllocator>::operator=(const TSet<TTuple<FName,FMaterialRecord>,TDefaultMapHashableKeyFuncs<FName,FMaterialRecord,0>,FDefaultSetAllocator> &) Set.h:345
[Inlined] TSet<TTuple<FName,FMaterialRecord>,TDefaultMapHashableKeyFuncs<FName,FMaterialRecord,0>,FDefaultSetAllocator>::{ctor}(const TSet<TTuple<FName,FMaterialRecord>,TDefaultMapHashableKeyFuncs<FName,FMaterialRecord,0>,FDefaultSetAllocator> &) Set.h:312
[Inlined] TMapBase<FName,FMaterialRecord,FDefaultSetAllocator,TDefaultMapHashableKeyFuncs<FName,FMaterialRecord,0> >::{ctor}(const TMapBase<FName,FMaterialRecord,FDefaultSetAllocator,TDefaultMapHashableKeyFuncs<FName,FMaterialRecord,0> > &) 0x00007ff7d0ea0c14
[Inlined] TSortableMapBase<FName,FMaterialRecord,FDefaultSetAllocator,TDefaultMapHashableKeyFuncs<FName,FMaterialRecord,0> >::{ctor}(const TSortableMapBase<FName,FMaterialRecord,FDefaultSetAllocator,TDefaultMapHashableKeyFuncs<FName,FMaterialRecord,0> > &) 0x00007ff7d0ea0c0b
[Inlined] TMap<FName,FMaterialRecord,FDefaultSetAllocator,TDefaultMapHashableKeyFuncs<FName,FMaterialRecord,0> >::{ctor}(const TMap<FName,FMaterialRecord,FDefaultSetAllocator,TDefaultMapHashableKeyFuncs<FName,FMaterialRecord,0> > &) 0x00007ff7d0ea0c0b
FSaviorRecord::FSaviorRecord(const FSaviorRecord &) 0x00007ff7d0ea0c0b
[Inlined] UE4Tuple_Private::TTupleBaseElement<FSaviorRecord,1,2>::{ctor}(const UE4Tuple_Private::TTupleBaseElement<FSaviorRecord,1,2> &) 0x00007ff7d0ea5a46
[Inlined] UE4Tuple_Private::TTupleBase<TIntegerSequence<unsigned int,0,1>,FName,FSaviorRecord>::{ctor}(const UE4Tuple_Private::TTupleBase<TIntegerSequence<unsigned int,0,1>,FName,FSaviorRecord> &) 0x00007ff7d0ea5a41
[Inlined] TTuple<FName,FSaviorRecord>::{ctor}(const TTuple<FName,FSaviorRecord> &) 0x00007ff7d0ea5a31
[Inlined] TSetElementBase<TTuple<FName,FSaviorRecord>,1>::{ctor}(const TSetElementBase<TTuple<FName,FSaviorRecord>,1> &) 0x00007ff7d0ea5a31
[Inlined] TSetElement<TTuple<FName,FSaviorRecord> >::{ctor}(const TSetElement<TTuple<FName,FSaviorRecord> > &) 0x00007ff7d0ea5a31
[Inlined] TSparseArray<TSetElement<TTuple<FName,FSaviorRecord> >,TSparseArrayAllocator<TSizedDefaultAllocator<32>,FDefaultBitArrayAllocator> >::operator=(const TSparseArray<TSetElement<TTuple<FName,FSaviorRecord> >,TSparseArrayAllocator<TSizedDefaultAllocator<32>,FDefaultBitArrayAllocator> > &) SparseArray.h:746
TSet<TTuple<FName,FSaviorRecord>,TDefaultMapHashableKeyFuncs<FName,FSaviorRecord,0>,FDefaultSetAllocator>::operator=(const TSet<TTuple<FName,FSaviorRecord>,TDefaultMapHashableKeyFuncs<FName,FSaviorRecord,0>,FDefaultSetAllocator> &) Set.h:345
[Inlined] TMapBase<FName,FSaviorRecord,FDefaultSetAllocator,TDefaultMapHashableKeyFuncs<FName,FSaviorRecord,0> >::operator=(const TMapBase<FName,FSaviorRecord,FDefaultSetAllocator,TDefaultMapHashableKeyFuncs<FName,FSaviorRecord,0> > &) 0x00007ff7d0f08efa
[Inlined] TSortableMapBase<FName,FSaviorRecord,FDefaultSetAllocator,TDefaultMapHashableKeyFuncs<FName,FSaviorRecord,0> >::operator=(const TSortableMapBase<FName,FSaviorRecord,FDefaultSetAllocator,TDefaultMapHashableKeyFuncs<FName,FSaviorRecord,0> > &) 0x00007ff7d0f08ef5
[Inlined] TMap<FName,FSaviorRecord,FDefaultSetAllocator,TDefaultMapHashableKeyFuncs<FName,FSaviorRecord,0> >::operator=(const TMap<FName,FSaviorRecord,FDefaultSetAllocator,TDefaultMapHashableKeyFuncs<FName,FSaviorRecord,0> > &) 0x00007ff7d0f08ef5
[Inlined] USavior::SlotDataToOBJ() 0x00007ff7d0f08ef5
USavior::WriteSlotToFile(const int,ESaviorResult &) 0x00007ff7d0f08e49
OnFinishSerializeLevel(USavior *,ESaviorResult,const bool) 0x00007ff7d0eef0f0
[Inlined] Invoke(void (*const &)(USavior *, ESaviorResult, bool),USavior *const &,const ESaviorResult &,const bool &) Invoke.h:51
[Inlined] UE4Tuple_Private::TTupleBase<TIntegerSequence<unsigned int,0,1,2>,USavior *,enum ESaviorResult,bool>::ApplyAfter(void (*const &)(USavior *, ESaviorResult, bool)) Tuple.h:306
TBaseStaticDelegateInstance<void __cdecl(void),FDefaultDelegateUserPolicy,USavior *,enum ESaviorResult,bool>::ExecuteIfSafe() DelegateInstancesImpl.h:729
[Inlined] TDelegate<void __cdecl(void),FDefaultDelegateUserPolicy>::ExecuteIfBound() DelegateSignatureImpl.inl:599
[Inlined] FSimpleDelegateGraphTask::DoTask(Type,const TRefCountPtr<FGraphEvent> &) TaskGraphInterfaces.h:1215
TGraphTask<FSimpleDelegateGraphTask>::ExecuteTask(TArray<FBaseGraphTask *,TSizedDefaultAllocator<32> > &,Type) TaskGraphInterfaces.h:886
<unknown> 0x00007ff7d150bb2b
<unknown> 0x00007ff7d150be5a
<unknown> 0x00007ff7d150c122
<unknown> 0x00007ff7d5ae7adc
<unknown> 0x00007ff7cfd78e80
<unknown> 0x00007ff7cfd8cd5f
<unknown> 0x00007ff7cfd8f297
<unknown> 0x00007ff7cfda0a74
[Inlined] invoke_main() 0x00007ff7d6d4fa2e
__scrt_common_main_seh() 0x00007ff7d6d4fa0d
<unknown> 0x00007ff91f9e7034
<unknown> 0x00007ff9219c2651

I will check that as soon as I can.
But looks like a tricky crash, it’s going to take some time to figure out if it’s bug in plugin.

I would disabled the functions that generate material records for now, if you don’t need them (you can edit source code of plugin).

Thank you,

Disabling the materials is not an option for us unfortunately as our software relies heavily on that feature. I will update here further if I find anything that may be of use to figuring out how this issue may be caused.

To add another crash log to the above. Seems to crash while trying to USavior::WriteToSlotFile

Gives the following crash:

Exception 0xc0000005 encountered at address 0x7ff79e75ab46: Access violation reading location 0x0000b780

<unknown> 0x00007ff79e75ab46
<unknown> 0x00007ff79e75a8cb
<unknown> 0x00007ff79e538ab5
<unknown> 0x00007ff79eae2f9e
<unknown> 0x00007ff79eb212c5
<unknown> 0x00007ff79e8f1b02
<unknown> 0x00007ff79e8ef688
<unknown> 0x00007ff79eb21092
<unknown> 0x00007ff79eae2e4a
<unknown> 0x00007ff79eb212c5
<unknown> 0x00007ff79e8f1b02
<unknown> 0x00007ff79ea7d2de
<unknown> 0x00007ff79ea7ace3
<unknown> 0x00007ff79ea7ab50
<unknown> 0x00007ff7a1f1d967
<unknown> 0x00007ff7a1f1d9fb
USavior::WriteSlotToFile(const int,ESaviorResult &) 0x00007ff79dc549f5
OnFinishSerializeLevel(USavior *,ESaviorResult,const bool) 0x00007ff79dc3abd0
[Inlined] Invoke(void (*const &)(USavior *, ESaviorResult, bool),USavior *const &,const ESaviorResult &,const bool &) Invoke.h:51
[Inlined] UE4Tuple_Private::TTupleBase<TIntegerSequence<unsigned int,0,1,2>,USavior *,enum ESaviorResult,bool>::ApplyAfter(void (*const &)(USavior *, ESaviorResult, bool)) Tuple.h:306
TBaseStaticDelegateInstance<void __cdecl(void),FDefaultDelegateUserPolicy,USavior *,enum ESaviorResult,bool>::ExecuteIfSafe() DelegateInstancesImpl.h:729
[Inlined] TDelegate<void __cdecl(void),FDefaultDelegateUserPolicy>::ExecuteIfBound() DelegateSignatureImpl.inl:599
[Inlined] FSimpleDelegateGraphTask::DoTask(Type,const TRefCountPtr<FGraphEvent> &) TaskGraphInterfaces.h:1215
TGraphTask<FSimpleDelegateGraphTask>::ExecuteTask(TArray<FBaseGraphTask *,TSizedDefaultAllocator<32> > &,Type) TaskGraphInterfaces.h:886
<unknown> 0x00007ff79e258dbb
<unknown> 0x00007ff79e25921e
<unknown> 0x00007ff79e267f96
<unknown> 0x00007ff7a2791fcc
<unknown> 0x00007ff7a2797454
<unknown> 0x00007ff7a20783cf
<unknown> 0x00007ff7a2083451
<unknown> 0x00007ff7a1ed267e
<unknown> 0x00007ff79cac1fc4
<unknown> 0x00007ff79cad883f
<unknown> 0x00007ff79cadad77
<unknown> 0x00007ff79caec554
[Inlined] invoke_main() 0x00007ff7a3a9cd2e
__scrt_common_main_seh() 0x00007ff7a3a9cd0d
<unknown> 0x00007ff91f9e7034
<unknown> 0x00007ff9219c2651

Please email me screenshots of your BP graphs, the places where you are executing “Save Level” nodes.

Alright, so I made a barebones example of using the save system as we use it, and it already crashes on just using a couple of nodes:

<unknown> 0x00007ff73f367f14
<unknown> 0x00007ff73f36e38c
<unknown> 0x00007ff73f36d1d5
<unknown> 0x00007ff73f3b0240
<unknown> 0x00007ff73f3b0532
<unknown> 0x00007ff73db581e7
TSet<TTuple<FGuid,FMatScalarRecord>,TDefaultMapHashableKeyFuncs<FGuid,FMatScalarRecord,0>,FDefaultSetAllocator>::operator=(const TSet<TTuple<FGuid,FMatScalarRecord>,TDefaultMapHashableKeyFuncs<FGuid,FMatScalarRecord,0>,FDefaultSetAllocator> &) Set.h:341
[Inlined] TSet<TTuple<FGuid,FMatScalarRecord>,TDefaultMapHashableKeyFuncs<FGuid,FMatScalarRecord,0>,FDefaultSetAllocator>::{ctor}(const TSet<TTuple<FGuid,FMatScalarRecord>,TDefaultMapHashableKeyFuncs<FGuid,FMatScalarRecord,0>,FDefaultSetAllocator> &) Set.h:312
[Inlined] TMapBase<FGuid,FMatScalarRecord,FDefaultSetAllocator,TDefaultMapHashableKeyFuncs<FGuid,FMatScalarRecord,0> >::{ctor}(const TMapBase<FGuid,FMatScalarRecord,FDefaultSetAllocator,TDefaultMapHashableKeyFuncs<FGuid,FMatScalarRecord,0> > &) 0x00007ff73ec5cbaa
[Inlined] TSortableMapBase<FGuid,FMatScalarRecord,FDefaultSetAllocator,TDefaultMapHashableKeyFuncs<FGuid,FMatScalarRecord,0> >::{ctor}(const TSortableMapBase<FGuid,FMatScalarRecord,FDefaultSetAllocator,TDefaultMapHashableKeyFuncs<FGuid,FMatScalarRecord,0> > &) 0x00007ff73ec5cbaa
[Inlined] TMap<FGuid,FMatScalarRecord,FDefaultSetAllocator,TDefaultMapHashableKeyFuncs<FGuid,FMatScalarRecord,0> >::{ctor}(const TMap<FGuid,FMatScalarRecord,FDefaultSetAllocator,TDefaultMapHashableKeyFuncs<FGuid,FMatScalarRecord,0> > &) 0x00007ff73ec5cbaa
FMaterialRecord::FMaterialRecord(const FMaterialRecord &) 0x00007ff73ec5cbaa
[Inlined] UE4Tuple_Private::TTupleBaseElement<FMaterialRecord,1,2>::{ctor}(const UE4Tuple_Private::TTupleBaseElement<FMaterialRecord,1,2> &) 0x00007ff73ec618d6
[Inlined] UE4Tuple_Private::TTupleBase<TIntegerSequence<unsigned int,0,1>,FName,FMaterialRecord>::{ctor}(const UE4Tuple_Private::TTupleBase<TIntegerSequence<unsigned int,0,1>,FName,FMaterialRecord> &) 0x00007ff73ec618d1
[Inlined] TTuple<FName,FMaterialRecord>::{ctor}(const TTuple<FName,FMaterialRecord> &) 0x00007ff73ec618c1
[Inlined] TSetElementBase<TTuple<FName,FMaterialRecord>,1>::{ctor}(const TSetElementBase<TTuple<FName,FMaterialRecord>,1> &) 0x00007ff73ec618c1
[Inlined] TSetElement<TTuple<FName,FMaterialRecord> >::{ctor}(const TSetElement<TTuple<FName,FMaterialRecord> > &) 0x00007ff73ec618c1
[Inlined] TSparseArray<TSetElement<TTuple<FName,FMaterialRecord> >,TSparseArrayAllocator<TSizedDefaultAllocator<32>,FDefaultBitArrayAllocator> >::operator=(const TSparseArray<TSetElement<TTuple<FName,FMaterialRecord> >,TSparseArrayAllocator<TSizedDefaultAllocator<32>,FDefaultBitArrayAllocator> > &) SparseArray.h:746
TSet<TTuple<FName,FMaterialRecord>,TDefaultMapHashableKeyFuncs<FName,FMaterialRecord,0>,FDefaultSetAllocator>::operator=(const TSet<TTuple<FName,FMaterialRecord>,TDefaultMapHashableKeyFuncs<FName,FMaterialRecord,0>,FDefaultSetAllocator> &) Set.h:345
[Inlined] TSet<TTuple<FName,FMaterialRecord>,TDefaultMapHashableKeyFuncs<FName,FMaterialRecord,0>,FDefaultSetAllocator>::{ctor}(const TSet<TTuple<FName,FMaterialRecord>,TDefaultMapHashableKeyFuncs<FName,FMaterialRecord,0>,FDefaultSetAllocator> &) Set.h:312
[Inlined] TMapBase<FName,FMaterialRecord,FDefaultSetAllocator,TDefaultMapHashableKeyFuncs<FName,FMaterialRecord,0> >::{ctor}(const TMapBase<FName,FMaterialRecord,FDefaultSetAllocator,TDefaultMapHashableKeyFuncs<FName,FMaterialRecord,0> > &) 0x00007ff73ec5ce14
[Inlined] TSortableMapBase<FName,FMaterialRecord,FDefaultSetAllocator,TDefaultMapHashableKeyFuncs<FName,FMaterialRecord,0> >::{ctor}(const TSortableMapBase<FName,FMaterialRecord,FDefaultSetAllocator,TDefaultMapHashableKeyFuncs<FName,FMaterialRecord,0> > &) 0x00007ff73ec5ce0b
[Inlined] TMap<FName,FMaterialRecord,FDefaultSetAllocator,TDefaultMapHashableKeyFuncs<FName,FMaterialRecord,0> >::{ctor}(const TMap<FName,FMaterialRecord,FDefaultSetAllocator,TDefaultMapHashableKeyFuncs<FName,FMaterialRecord,0> > &) 0x00007ff73ec5ce0b
FSaviorRecord::FSaviorRecord(const FSaviorRecord &) 0x00007ff73ec5ce0b
[Inlined] UE4Tuple_Private::TTupleBaseElement<FSaviorRecord,1,2>::{ctor}(const UE4Tuple_Private::TTupleBaseElement<FSaviorRecord,1,2> &) 0x00007ff73ec61c46
[Inlined] UE4Tuple_Private::TTupleBase<TIntegerSequence<unsigned int,0,1>,FName,FSaviorRecord>::{ctor}(const UE4Tuple_Private::TTupleBase<TIntegerSequence<unsigned int,0,1>,FName,FSaviorRecord> &) 0x00007ff73ec61c41
[Inlined] TTuple<FName,FSaviorRecord>::{ctor}(const TTuple<FName,FSaviorRecord> &) 0x00007ff73ec61c31
[Inlined] TSetElementBase<TTuple<FName,FSaviorRecord>,1>::{ctor}(const TSetElementBase<TTuple<FName,FSaviorRecord>,1> &) 0x00007ff73ec61c31
[Inlined] TSetElement<TTuple<FName,FSaviorRecord> >::{ctor}(const TSetElement<TTuple<FName,FSaviorRecord> > &) 0x00007ff73ec61c31
[Inlined] TSparseArray<TSetElement<TTuple<FName,FSaviorRecord> >,TSparseArrayAllocator<TSizedDefaultAllocator<32>,FDefaultBitArrayAllocator> >::operator=(const TSparseArray<TSetElement<TTuple<FName,FSaviorRecord> >,TSparseArrayAllocator<TSizedDefaultAllocator<32>,FDefaultBitArrayAllocator> > &) SparseArray.h:746
TSet<TTuple<FName,FSaviorRecord>,TDefaultMapHashableKeyFuncs<FName,FSaviorRecord,0>,FDefaultSetAllocator>::operator=(const TSet<TTuple<FName,FSaviorRecord>,TDefaultMapHashableKeyFuncs<FName,FSaviorRecord,0>,FDefaultSetAllocator> &) Set.h:345
[Inlined] TMapBase<FName,FSaviorRecord,FDefaultSetAllocator,TDefaultMapHashableKeyFuncs<FName,FSaviorRecord,0> >::operator=(const TMapBase<FName,FSaviorRecord,FDefaultSetAllocator,TDefaultMapHashableKeyFuncs<FName,FSaviorRecord,0> > &) 0x00007ff73ecc50fa
[Inlined] TSortableMapBase<FName,FSaviorRecord,FDefaultSetAllocator,TDefaultMapHashableKeyFuncs<FName,FSaviorRecord,0> >::operator=(const TSortableMapBase<FName,FSaviorRecord,FDefaultSetAllocator,TDefaultMapHashableKeyFuncs<FName,FSaviorRecord,0> > &) 0x00007ff73ecc50f5
[Inlined] TMap<FName,FSaviorRecord,FDefaultSetAllocator,TDefaultMapHashableKeyFuncs<FName,FSaviorRecord,0> >::operator=(const TMap<FName,FSaviorRecord,FDefaultSetAllocator,TDefaultMapHashableKeyFuncs<FName,FSaviorRecord,0> > &) 0x00007ff73ecc50f5
[Inlined] USavior::SlotDataToOBJ() 0x00007ff73ecc50f5
USavior::WriteSlotToFile(const int,ESaviorResult &) 0x00007ff73ecc5049
OnFinishSerializeLevel(USavior *,ESaviorResult,const bool) 0x00007ff73ecab2f0
[Inlined] Invoke(void (*const &)(USavior *, ESaviorResult, bool),USavior *const &,const ESaviorResult &,const bool &) Invoke.h:51
[Inlined] UE4Tuple_Private::TTupleBase<TIntegerSequence<unsigned int,0,1,2>,USavior *,enum ESaviorResult,bool>::ApplyAfter(void (*const &)(USavior *, ESaviorResult, bool)) Tuple.h:306
TBaseStaticDelegateInstance<void __cdecl(void),FDefaultDelegateUserPolicy,USavior *,enum ESaviorResult,bool>::ExecuteIfSafe() DelegateInstancesImpl.h:729
[Inlined] TDelegate<void __cdecl(void),FDefaultDelegateUserPolicy>::ExecuteIfBound() DelegateSignatureImpl.inl:599
[Inlined] FSimpleDelegateGraphTask::DoTask(Type,const TRefCountPtr<FGraphEvent> &) TaskGraphInterfaces.h:1215
TGraphTask<FSimpleDelegateGraphTask>::ExecuteTask(TArray<FBaseGraphTask *,TSizedDefaultAllocator<32> > &,Type) TaskGraphInterfaces.h:886
<unknown> 0x00007ff73f2c933b
<unknown> 0x00007ff73f2c966a
<unknown> 0x00007ff73f2c9932
<unknown> 0x00007ff7438a535c
<unknown> 0x00007ff73db35080
<unknown> 0x00007ff73db48f5f
<unknown> 0x00007ff73db4b497
<unknown> 0x00007ff73db5cc74
[Inlined] invoke_main() 0x00007ff744b0d2ae
__scrt_common_main_seh() 0x00007ff744b0d28d
<unknown> 0x00007ff91f9e7034
<unknown> 0x00007ff9219c2651

and another crash log:

<unknown> 0x00007ff73f7cb0c6
<unknown> 0x00007ff73f7cae4b
<unknown> 0x00007ff73f5a9035
<unknown> 0x00007ff73fb5351e
<unknown> 0x00007ff73fb91845
<unknown> 0x00007ff73f962082
<unknown> 0x00007ff73f95fc08
<unknown> 0x00007ff73fb91612
<unknown> 0x00007ff73fb533ca
<unknown> 0x00007ff73fb91845
<unknown> 0x00007ff73f962082
<unknown> 0x00007ff73faed85e
<unknown> 0x00007ff73faeb263
<unknown> 0x00007ff73faeb0d0
<unknown> 0x00007ff742f8dee7
<unknown> 0x00007ff742f8df7b
USavior::WriteSlotToFile(const int,ESaviorResult &) 0x00007ff73ecc5115
OnFinishSerializeLevel(USavior *,ESaviorResult,const bool) 0x00007ff73ecab2f0
[Inlined] Invoke(void (*const &)(USavior *, ESaviorResult, bool),USavior *const &,const ESaviorResult &,const bool &) Invoke.h:51
[Inlined] UE4Tuple_Private::TTupleBase<TIntegerSequence<unsigned int,0,1,2>,USavior *,enum ESaviorResult,bool>::ApplyAfter(void (*const &)(USavior *, ESaviorResult, bool)) Tuple.h:306
TBaseStaticDelegateInstance<void __cdecl(void),FDefaultDelegateUserPolicy,USavior *,enum ESaviorResult,bool>::ExecuteIfSafe() DelegateInstancesImpl.h:729
[Inlined] TDelegate<void __cdecl(void),FDefaultDelegateUserPolicy>::ExecuteIfBound() DelegateSignatureImpl.inl:599
[Inlined] FSimpleDelegateGraphTask::DoTask(Type,const TRefCountPtr<FGraphEvent> &) TaskGraphInterfaces.h:1215
TGraphTask<FSimpleDelegateGraphTask>::ExecuteTask(TArray<FBaseGraphTask *,TSizedDefaultAllocator<32> > &,Type) TaskGraphInterfaces.h:886
<unknown> 0x00007ff73f2c933b
<unknown> 0x00007ff73f2c966a
<unknown> 0x00007ff73f2c9932
<unknown> 0x00007ff7438a535c
<unknown> 0x00007ff73db35080
<unknown> 0x00007ff73db48f5f
<unknown> 0x00007ff73db4b497
<unknown> 0x00007ff73db5cc74
[Inlined] invoke_main() 0x00007ff744b0d2ae
__scrt_common_main_seh() 0x00007ff744b0d28d
<unknown> 0x00007ff91f9e7034
<unknown> 0x00007ff9219c2651

and the Blueprint graph:

This is all there is to it really. Crash happens frequently when trying to save (relatively) a lot of actors, but also sometimes occurs when trying to save like 10 actors (just not as likely as trying to save 100)

I believe the MaterialRecord list must be moved out of actor records.
I will try some tests when I am out of work, this weekend.

void USavior::FindSlotFile(ESaviorResult &Result) {
	LOG_SV(true,ESeverity::Warning,GetSlotName());
	if (!UGameplayStatics::DoesSaveGameExist(GetSlotName(),0))
	{
		Result = ESaviorResult::Failed;
	}
	//
	Result = ESaviorResult::Success;
}

Also, the FindSlotFile method always return Success since it doesnt return after setting the result to Failed if the slot file does not exist.

I have fixed the crash trace you posted, on Unreal 5.
When I port the fix to UE4 I will submit an update.

Awesome! Thank you very much, we’re very excited to try the changes! :slight_smile:

Hi Bruno, I found another small issue:

When trying to run from a stand-alone build in Editor (UE5.0) the game crashes on line 1582 in the Savior.cpp file. Viewport and shipping builds work fine. Just wanted to let you know.

if (UGameInstance*const&GI=InWorld->GetGameInstance())
InWorld is probably null

LoginId:3a8d9698417d76280530bfa0f2ce01b9
EpicAccountId:b1b12906b40246d1bbdf45784ad2b158

Unhandled Exception: EXCEPTION_ACCESS_VIOLATION reading address 0x00000000000001e8

UnrealEditor_Engine
UnrealEditor_Savior!USavior::StaticLoadGameWorld() [D:\build\U5M-Marketplace\Sync\LocalBuilds\PluginTemp\HostProject\Plugins\Savior\Source\Savior\Private\Savior.cpp:1582]
UnrealEditor_Savior!TBaseUObjectMethodDelegateInstance<0,USavior,void __cdecl(UWorld *),FDefaultDelegateUserPolicy>::ExecuteIfSafe() [D:\RocketSync\5.0.0-19505902+++UE5+Release-5.0\Working\Engine\Source\Runtime\Core\Public\Delegates\DelegateInstancesImpl.h:611]
UnrealEditor_Engine
UnrealEditor_Engine
UnrealEditor_Engine
UnrealEditor_Engine
UnrealEditor_Engine
UnrealEditor
UnrealEditor
UnrealEditor
UnrealEditor
UnrealEditor
UnrealEditor
kernel32
ntdll