LCVg's Serialized Saves Plugin

[NEWS] Update 1.4 Coming at the end of next week!

I’m almost finished with Update 1.4. What it will include:

New Features:

. Automatic Savign for Map Objects: Objects that belong only to a determinated map will be saved automatically.
. Automatic Saving for Player Objects: Objects that should always exist in the game and belong to a player will be saved separately.
. Automatic referentiation for Objects (Experimental, needs a lot of testing).
. A new low level node to Async Load a class by its name.
. A new node to get an array of persistent objects.
. A new LCSObjectBase class for you to use optionally with added functionality (access to Unreal Static Library, among other things).
. New nodes to acces saved date directly in the Lost Cause Save Game Object.

Changes:
. Nodes like: “Direct Save Persistent Actors” are now renamed to “Direct Save Persistent Objects”. The user will not need to change nodes.

Bugfixes: To be listed on release.

New Platform Suport (Experimental):
. Mac
. IOs

This update is planed to be submitted to the Unreal Engine Marketplace on Wednesday the 16th. Expect it to be released to te public around friday the 18th.

Planned Updates:
This planned updates are for you to take as a reference for what to expect in the future. Take in account that Bug fixing wil always be the #1 priority.

. A UMG example menu for selecting save games.
. Multiple Slot support for each player (for them to be able to save multiple games per file).
. Async Load for objects and actors.

I’m also thinking on replacing this forum thread for support with a Discord Chanel so you guys can not only seek for help but input your feedback and ideas. Let me know what you think! Have a nice day!

[submitted to the marketplace] version 1.4r1 full update notes

[New Features]

  • Automatic Saving and Loading for UObjects:
    • Persistent UObjects are divided in Player Linked UObjects and Map Linked UObjects. - Player linked UObjects are saved apart so they can be always loaded. NOTE that this objects are meant for Gameplay usage and not for storing config data. This means they will always be loaded as long as the player controls a Pawn or Character.
      –How To-- To link an object to a player override the interface event called “IsLinkedToPlayer” for it to return True in your UObject blueprint or Cpp file.
    • Map UObjects will only be loaded on the map they where saved. This will help keeping the Save files organized and avoid loading useless data.
  • Automatic Re Referenciation of Persistent UObjects:
    • [Experimental] With some code magic saved uobjects that are referenced on any persistent actor, uobject or player pawn are now automatically referenced regardless of the loading context. This is especially important for Player Linked UObjects since they can be loaded in any map, even in those they were not created in!
      –How To— If you don’t want a persistent object to be automatically re referenced please mark the variable that references it as “transient”. Note that this might cause your objects to get garbage collected if they are not referenced shortly after being loaded as the plugin forces garbage collection.
  • A new node called “Get Persistent Objects” will return three different arrays that will contain PlayerUObjects, MapUObjects and MapAActors.
  • ULCSObjectBase: This useful class is a regular UObject except it has acces to Unreal Engine Static Library and to the Lost Cause Save System Library. Take in account that this object does not inherits the Persistent Object interface and if you want your inherited classes to be persistent you need to implement it.
  • A new node called “Create LCSObject of Class”
  • Mac and IOs support: The plugin can now be used for Mac and IOs development. Please take into account that you need to have XCode installed for it to work!
  • Unreal Engine 4.17 support.

[Changes]

  • Every function in the library that used to be called with Actors is now called with Objects as name: e.g LoadPersistentActors is now called LoadPersistentObjects. This is only a cosmetic change and the user needs to do nothing for it to work.

[Bug Fixes]

  • Corrected a bug that caused actors to not be loaded under some circumstances. Please note that when loading and saving it is FUNDAMENTAL that you pass a VALID LostCauseSaveGameObject into the functions for them to work correctly and avoid crashes. Be sure to initialize this object with the GetLCSaveGame function and NOT by CreateSaveGameObject. After loading always reasign the loaded save game object to your reference!
  • Fixed a crash being caused by functions getting invalid Save game references. From now on this functions will fail silently instead of crashing (it will appear as the plugin does nothing, if this happens be sure that your save game is correctly initialized).
    **
    [Known Issues, limitations]**
  • Old Saves are no longer compatible with the new version. Take this into account before you update!
  • References in non player linked UObjects to the player pawn are not always correctly restored. Please note that this is an experimental feature and you should avoid cross referencing when it comes to Persistent UObjects.
  • UObjects Arrays are not directly supported by the auto referencing system. While it, in some ocations, works out of the box you should avoid its use (mark your Persistent UObject arrays as transient), instead make your UObjects add themselves to said arrays after being loaded.
  • UActorComponents will be ignored by the auto reference system since they are not directly supported. Even if marked as Persistent. Avoid crashes by allocating your variables somewhere else.
    **
    [DOCUMENTATION]**
    Documentation is in process of being updated but it might take some time for it to be complete. Please refer to this notes and the support thread if there is missing information or there is something that requires clarification.

Any update on this? I just got back from a few weeks out of town, and it’s fantastic to see that osx progress has been made.

I received no update from Epic. I believe this is due the updates they are making to the marketplace. The update has been submitted but i had no response from them. I have sent an email to see whats what.

I’ll stay tuned!

Update 1.4r2 is now live :slight_smile: (finally). Have a nice weekend!

I’m unable to install this to mac through the marketplace, and Xcode is installed. It looks like it isn’t yet certified for Mac?

Yes. It seems like it. I have reached epic to find out why the binaries for mac are not included. Thank you for pointing it out.

I can not load the save either in my project, not in the example, always crash when loading :frowning: UE version 4.17.2


Fatal error!

Unhandled Exception: EXCEPTION_ACCESS_VIOLATION reading address 0xffffffff

UE4Editor-CoreUObject.dll!0x00000000DAEB4E66
UE4Editor-LCVgsSerializedSaves.dll!ULostCauseSaveGame::RestoreUObjectReferencesIn() [d:\build\++portal+dev-marketplace+full\sync\localbuilds\plugintemp\hostproject\plugins\lcvgsserializedsaves\source\lcvgsserializedsaves\private\lostcausesavegame.cpp:136]
UE4Editor-LCVgsSerializedSaves.dll!ULostCauseSaveSystemLibrary::RestoreUObjectReferencesForPlayer() [d:\build\++portal+dev-marketplace+full\sync\localbuilds\plugintemp\hostproject\plugins\lcvgsserializedsaves\source\lcvgsserializedsaves\private\lostcausesavesystemlibrary.cpp:388]
UE4Editor-LCVgsSerializedSaves.dll!ULostCauseSaveSystemLibrary::FinishLoad() [d:\build\++portal+dev-marketplace+full\sync\localbuilds\plugintemp\hostproject\plugins\lcvgsserializedsaves\source\lcvgsserializedsaves\private\lostcausesavesystemlibrary.cpp:654]
UE4Editor-LCVgsSerializedSaves.dll!ULCTimerHelper::FinishGameLoad() [d:\build\++portal+dev-marketplace+full\sync\localbuilds\plugintemp\hostproject\plugins\lcvgsserializedsaves\source\lcvgsserializedsaves\private\lctimerhelper.cpp:48]
UE4Editor-Engine.dll!0x00000000D881E520
UE4Editor-Engine.dll!0x00000000D886C9DE
UE4Editor-Engine.dll!0x00000000D80DC41B
UE4Editor-UnrealEd.dll!0x00000000D49DC982
UE4Editor-UnrealEd.dll!0x00000000D526D646
UE4Editor.exe!0x000000003FDC534A
UE4Editor.exe!0x000000003FDD3970
UE4Editor.exe!0x000000003FDD39EA
UE4Editor.exe!0x000000003FDE02D9
UE4Editor.exe!0x000000003FDE1C47
kernel32.dll!0x0000000076D659CD
ntdll.dll!0x0000000076E9A561
ntdll.dll!0x0000000076E9A561


The compiled version of the sample project also crashes when you click “Load last save” with the message Fatal error :frowning:

UPD. Example in the version UE 4.16.3 everything works fine …

Sorry for my English.

Hey there, I bought the plug-in a few weeks ago for my project - only recently got around to implementing it. Looks very promising, and I’m a fan of how simplified the system is. However, I cannot seem to get it to work without crashing my engine on load. The root problem seems to be that it destroys all objects during a load, and doesn’t add in loaded versions. It seems like a setup problem, but I’ve been banging my head against this for a few days, and cannot for the life of me see what I’m doing wrong.
Here’s my process:

  1. My very simple testing scenario. The player does not have a component on them, the rat does.
    https://s1.postimg.org/4kibrr0gj3/LC0.jpg

  2. The save code, as executed from a save menu spawned by the save point. Save files get their names from the Game Instance which has hard-coded names for its saves. (SaveSlot1, SaveSlot2, SaveSlot3)
    https://s1.postimg.org/7fazxjlfmn/LC1.jpg

  3. Testing and confirming the save registers in the correct slot.
    https://s1.postimg.org/1t99joppfj/LC2.jpg

  4. Part 1 of the load code. BPI message executed from a UMG menu.
    https://s1.postimg.org/1x5mvki02l/LC3.jpg

  5. Part 2 of the load code. GameMode listening to the BPI and loading the appropriate slot.
    https://s1.postimg.org/2wlq8qswfz/LC4.jpg

  6. The symptom of the problem. Upon load, both the player and the rat delete and do not load back.
    https://s1.postimg.org/7cgws61qa7/LC5.jpg

  7. The engine promptly crashes after stopping the session, with no debug (I imagine because there isn’t a player).
    https://s1.postimg.org/8tn1tx806n/LC6.jpg

It seems that there is a bug with the 4.17 version of the plugin. I’m looking into this issue. Thanks for pointing it out.
Edit: the reason for it not showing any debug code is because you have not installed the debug symbols of the engine. It would be really helpful if you did.

I’m working on a fix. Thanks for pointing this out

UE 4.17.2 HOTFIX

This update is pending review from EPIC but should be online very soon.

The function LoadLCSaveGame has been replaced with one that receives a LCSaveGame as input. The other one is deprecated and will continue to cause crashes. Please use the new Load Lost Cause Save Game function instead as shown in the image below:

Further updates will completly remove the older function in the new and previous releases of the engine. The idea is to replace both of this functions with a latent function that will get rid of crashes once and for all.

IMPORTANT NOTE: Do NOT create the LCSaveGame Object in the same frame that you will call this functions. Using a Dealy Node will not work.

Hey Bariudol, it seems that you found your problem.
It likely does not help anymore, but here’s the crash in full that I get when using the old save / load system.
https://s1.postimg.org/1nrrk1md0v/LC7.jpg

[SPOILER]


Assertion failed: !IsRooted() [File:D:\Build\++UE4+Release-4.17+Compile\Sync\Engine\Source\Runtime\CoreUObject\Public\UObject/UObjectBaseUtility.h] [Line: 139]

UE4Editor_Core!FDebug::AssertFailed() [d:\build\++ue4+release-4.17+compile\sync\engine\source\runtime\core\private\misc\assertionmacros.cpp:349]
UE4Editor_Engine!<lambda_784de1c996c3a8178fcc0fdd6f0705e5>::operator()() [d:\build\++ue4+release-4.17+compile\sync\engine\source\runtime\engine\private\world.cpp:1384]
UE4Editor_CoreUObject!ForEachObjectWithOuter() [d:\build\++ue4+release-4.17+compile\sync\engine\source\runtime\coreuobject\private\uobject\uobjecthash.cpp:705]
UE4Editor_Engine!UWorld::MarkObjectsPendingKill() [d:\build\++ue4+release-4.17+compile\sync\engine\source\runtime\engine\private\world.cpp:1387]
UE4Editor_UnrealEd!UEditorEngine::EndPlayMap() [d:\build\++ue4+release-4.17+compile\sync\engine\source\editor\unrealed\private\playlevel.cpp:411]
UE4Editor_UnrealEd!UEditorEngine::Tick() [d:\build\++ue4+release-4.17+compile\sync\engine\source\editor\unrealed\private\editorengine.cpp:1908]
UE4Editor_UnrealEd!UUnrealEdEngine::Tick() [d:\build\++ue4+release-4.17+compile\sync\engine\source\editor\unrealed\private\unrealedengine.cpp:402]
UE4Editor!FEngineLoop::Tick() [d:\build\++ue4+release-4.17+compile\sync\engine\source\runtime\launch\private\launchengineloop.cpp:3215]
UE4Editor!GuardedMain() [d:\build\++ue4+release-4.17+compile\sync\engine\source\runtime\launch\private\launch.cpp:166]
UE4Editor!GuardedMainWrapper() [d:\build\++ue4+release-4.17+compile\sync\engine\source\runtime\launch\private\windows\launchwindows.cpp:134]
UE4Editor!WinMain() [d:\build\++ue4+release-4.17+compile\sync\engine\source\runtime\launch\private\windows\launchwindows.cpp:210]
UE4Editor!__scrt_common_main_seh() [f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl:253]
kernel32
ntdll

[/SPOILER]

I eagerly await the update from Epic. If we cannot create the SaveGame Object or use a delay node, am I to assume that the save game should already exist in some form before we call load? Is “Get LCSave Game” a valid way to get the save game before loading?

Yes. You must create the save game object with that function. Just not in the same frame you load. For instance you can create it at begin play and asign the value to a variable and then use that variable to load the game. Just remember to not create the dave game object and loading in the same frame.

I know its not the best solution but for now its the only workaround. This should be fixed in the next update of the plugin.

Well, on the plus side, I did manage to get the update. Very prompt!
Unfortunately, I still appear to be getting crashes related to deleting all save objects with an !IsRooted error.
Here’s my current setup:

I set the save game variables on Begin Play of the parent GameMode class. With my debug print, I can see this executes properly.
https://s1.postimg.org/8mzphmbd7z/LC8.jpg

Now, with a very similar setup as before, I load the game - but now supply a save game, instead of a save slot name. The message is sent via Blueprint Interface to the GameMode.
https://s1.postimg.org/40e2gxoly7/LC9.jpg

Then the game mode simply loads the game from that save file, using the new method.
https://s1.postimg.org/6ztworudhr/LC10.jpg

I’m a bit questioning of wither my problem is related to 4.17 at all. Originally, I had my game running on 4.15.2, and only recently updated because I thought my save / load problem, might be related to something being out of date.
Could there be anything with my setup that’s screwing up the save load?

I’ll try to reproduce the issue to find a solution for it. But at first sight the reason for the crash is that you are creating the saveobjects and loading the game in the same frame if your main menu mode is set to ignore it. In 4.17 and later you have to avoid this, thats the main reason for deprecating the function. In short dont create the object on begin play and load in begin play.

In the next update this should be solved completly.

Alright, I think I managed to find out what my problem was, definitely something up with my setup. I played around with when I do get for the save game, being very careful now so that it only happens at the start of the main menu. Another part of it was that my game was paused when I saved, and wouldn’t be unpaused when I loaded, so I guess the code for loading in actors never executed. Lesson learned.

Strange thing now is that I’m getting a different crash. If I start a new game, save, and then load or start a new game, save, go to the main menu, and then load - the game will crash.
However, if I start a new game, save, then quit and start a new session, then load (either from a new game, or a new level), the game loads perfectly fine. Very odd.

Here’s the full code for the crash, if you would like to see: [SPOILER]



 LoginId:57f60df5478bda0901a0509259c63b87
EpicAccountId:2ff5e32898f54806ad9f63e9b229fd65

Access violation - code c0000005 (first/second chance not available)

UE4Editor_Engine!UGameViewportClient::InputKey() [d:\build\++ue4+release-4.17+compile\sync\engine\source\runtime\engine\private\gameviewportclient.cpp:410]
UE4Editor_Engine!FSceneViewport::OnKeyUp() [d:\build\++ue4+release-4.17+compile\sync\engine\source\runtime\engine\private\slate\sceneviewport.cpp:935]
UE4Editor_Slate!SViewport::OnKeyUp() [d:\build\++ue4+release-4.17+compile\sync\engine\source\runtime\slate\private\widgets\sviewport.cpp:245]
UE4Editor_Slate!<lambda_6edabb7999d104566d200ed4979fb141>::operator()() [d:\build\++ue4+release-4.17+compile\sync\engine\source\runtime\slate\private\framework\application\slateapplication.cpp:4829]
UE4Editor_Slate!FEventRouter::Route<FReply,FEventRouter::FBubblePolicy,FKeyEvent,<lambda_6edabb7999d104566d200ed4979fb141> >() [d:\build\++ue4+release-4.17+compile\sync\engine\source\runtime\slate\private\framework\application\slateapplication.cpp:232]
UE4Editor_Slate!FEventRouter::RouteAlongFocusPath<FEventRouter::FBubblePolicy,<lambda_6edabb7999d104566d200ed4979fb141>,FKeyEvent>() [d:\build\++ue4+release-4.17+compile\sync\engine\source\runtime\slate\private\framework\application\slateapplication.cpp:214]
UE4Editor_Slate!FSlateApplication::ProcessKeyUpEvent() [d:\build\++ue4+release-4.17+compile\sync\engine\source\runtime\slate\private\framework\application\slateapplication.cpp:4827]
UE4Editor_Slate!FSlateApplication::OnKeyUp() [d:\build\++ue4+release-4.17+compile\sync\engine\source\runtime\slate\private\framework\application\slateapplication.cpp:4795]
UE4Editor_Core!FWindowsApplication::ProcessDeferredMessage() [d:\build\++ue4+release-4.17+compile\sync\engine\source\runtime\core\private\windows\windowsapplication.cpp:1633]
UE4Editor_Core!FWindowsApplication::DeferMessage() [d:\build\++ue4+release-4.17+compile\sync\engine\source\runtime\core\private\windows\windowsapplication.cpp:2161]
UE4Editor_Core!FWindowsApplication::ProcessMessage() [d:\build\++ue4+release-4.17+compile\sync\engine\source\runtime\core\private\windows\windowsapplication.cpp:881]
UE4Editor_Core!FWindowsApplication::AppWndProc() [d:\build\++ue4+release-4.17+compile\sync\engine\source\runtime\core\private\windows\windowsapplication.cpp:721]
user32
user32
UE4Editor_Core!FWindowsPlatformMisc::PumpMessages() [d:\build\++ue4+release-4.17+compile\sync\engine\source\runtime\core\private\windows\windowsplatformmisc.cpp:1009]
UE4Editor!FEngineLoop::Tick() [d:\build\++ue4+release-4.17+compile\sync\engine\source\runtime\launch\private\launchengineloop.cpp:3151]
UE4Editor!GuardedMain() [d:\build\++ue4+release-4.17+compile\sync\engine\source\runtime\launch\private\launch.cpp:166]
UE4Editor!GuardedMainWrapper() [d:\build\++ue4+release-4.17+compile\sync\engine\source\runtime\launch\private\windows\launchwindows.cpp:134]
UE4Editor!WinMain() [d:\build\++ue4+release-4.17+compile\sync\engine\source\runtime\launch\private\windows\launchwindows.cpp:210]
UE4Editor!__scrt_common_main_seh() [f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl:253]
kernel32
ntdll


[/SPOILER]

Thanks for the report. I will work on a fix to this during this and next week so we can forget about the crashes. Thanks a lot for your help.

Glad to help, it’s certainly in both our best interest to get these problems solved.
Just re-reading what I wrote at 1:30AM last night, and the reproduction instructions are quite confusing, haha. Here’s it more clearly.

To crash in my game: [SPOILER]

  • Begin a play session, with no save files in the save directory.
  • Start a new game.
  • Go to a save point and save.
  • Afterwords, load the game while still playing - OR - back out to the main menu and load the game there.
  • Crash

[/SPOILER]
To avoid this crash:
[SPOILER]

  • Begin a play session, with no save files in the save directory.
  • Start a new game.
  • Go to a save point and save.
  • Afterwords, close or quit the game. End the play session.
  • Start a new play session.
  • Start a new game and immediately load the old save - OR - simply load the old save from the main menu.

[/SPOILER]