Binary Compressed Save System, Save Entire Dynamically Generated Worlds! ♥ Rama

Here’s the Game State interface that I implemented. I’m sure you can easily figure out where the hooks go if you’re interested :slight_smile: Provides a nice way for me to get global notifications on save events.



#pragma once

#include "CoreMinimal.h"
#include "RamaSaveGameStateInterface.generated.h"


DECLARE_DYNAMIC_MULTICAST_DELEGATE(FRamaSaveGameStateFullyLoadedSignature);
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FRamaSaveGameStatePreSaveSignature);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FRamaSaveGameStatePlayerLoadedSignature, APlayerController*, PC, APawn*, Pawn, int32, PlayerIndex);
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FRamaSaveGameStatePreLoadDestroySignature);


UINTERFACE(Blueprintable, MinimalAPI)
class URamaSaveGameStateInterface : public UInterface
{
    GENERATED_UINTERFACE_BODY()
};

/**
 * Add this interface to your GameState class to get global notifications for save events.
 */
class RAMASAVESYSTEM_API IRamaSaveGameStateInterface
{
    GENERATED_IINTERFACE_BODY()

public:

    // Called when all actors are fully loaded
    UFUNCTION(Category = "Rama Save System", BlueprintCallable, BlueprintNativeEvent)
    void OnRamaSaveFullyLoaded();

    // Called before actors are saved
    UFUNCTION(Category = "Rama Save System", BlueprintCallable, BlueprintNativeEvent)
    void OnRamaSavePreSave();

    // Called when the specified player is loaded
    UFUNCTION(Category = "Rama Save System", BlueprintCallable, BlueprintNativeEvent)
    void OnRamaSavePlayerLoaded(APlayerController* PC, APawn* Pawn, int32 PlayerIndex);

    // Called before actors are destroyed in preparation for a load
    UFUNCTION(Category = "Rama Save System", BlueprintCallable, BlueprintNativeEvent)
    void OnRamaSavePreLoadDestroy();
};

When loading a level, is there a way to try and handle levels from a previous patch? Don’t want people loosing their progress.

NOTE: We are still on UE4.16, maybe you changed that already.
Edit: Just had a look, still exists in UE4.18

Hey Rama. I would like to determine if an actor should be saved or not in RamaSaveEvent_PreSave.
This does not work as you


    if(!EachSaveComp->RamaSave_ShouldSaveActor)
        {
            CompCountNotBeingSaved++;
        }

before you call


EachSaveComp->RamaCPP_PreSave();

Thus when changing RamaSave_ShouldSaveActor in some PreSave function, it will save accordingly but the memory allocation 'n stuff is wrong.

Just swap the call order and it should be fine.

Having a realy hard time here using a custom RamaSaveEngine class.

The issue: Can’t start the editor any more. Getting a crash during editor loading at 71%.
Here the log from VisualStudio:



'UE4Editor.exe' (Win32): Loaded 'C:\Program Files\Epic Games\UE_4.16\Engine\Plugins\Editor\FacialAnimation\Binaries\Win64\UE4Editor-FacialAnimation.dll'. Symbols loaded.
'UE4Editor.exe' (Win32): Loaded 'C:\Program Files\Epic Games\UE_4.16\Engine\Plugins\Editor\FacialAnimation\Binaries\Win64\UE4Editor-FacialAnimationEditor.dll'. Symbols loaded.
'UE4Editor.exe' (Win32): Loaded 'C:\Program Files\Epic Games\UE_4.16\Engine\Plugins\Editor\GameplayTagsEditor\Binaries\Win64\UE4Editor-GameplayTagsEditor.dll'. Symbols loaded.
'UE4Editor.exe' (Win32): Loaded 'C:\Program Files\Epic Games\UE_4.16\Engine\Plugins\Marketplace\RamaSaveSystem\Binaries\Win64\UE4Editor-RamaSaveSystem.dll'. Symbols loaded.
[2018.02.23-19.25.28:387]  0]LogLinker: Can't find file '/Script/AdvancedSessions'
[2018.02.23-19.25.28:387]  0]LogLinker: Can't find file for asset '/Script/AdvancedSessions' while loading ...
...

The log goes on and on and on. Tons of Can’t find file and stuff. As you can see the issues first start occouring after UE4Editor-RamaSaveSystem.dll was loaded.
Removing the line from the DefaultGame.ini that specifies my custom RamaSaveClass, I can load the project as usual.
At some point visual studio has a null access, allways at the same codeline, always the same class PropertyTag.cpp line 58. It wants to save a property of a class that is not related to the custom RamaSaveEngine class. But after tons of errors with loading, that error is telling nothing.

It took me a long time to narrow the cause down. At this point it seems to crash when the custom RamaSaveEngine class references another custom class IN ANY KIND OF WAY. Even an empty custom RamaSaveEngine with ONLY a CreateWidget node in it that references another custom class, will cause the crash. The node is not even connected to anything. No variables.

Unfortunately I was not able to recreate the issue in a fresh project (UE4.16).

@Rama, I’ve got a weird one here, but figured out how to work around it. For some reason, a component that lives on an actor I’m saving/loading w/ the RamaSaveSystem is lost upon loading. Like, the component just isn’t there anymore upon reload. Well, either that or all references to this component are borked.

As a test, I added this debug output on the actor that owns the component.

Before I save/load, I’m getting flooded w/ debug output referencing the components. After a save/load, it doesn’t find any of the components.

HOWEVER, if I give these actors a Guid on the save component and therefore don’t destroy/create upon loading, debug output continues to flood after a save/load and everything is all good.

I realize this is kind of a weird one, but maybe you’ve got an idea as to what’s happening? I’ve got a work around so I’m happy, but thought it was worth noting!

Thanks!

Eek. This problem just surfaced in another area that I can’t work around. For some reason, objects that are destroyed for a load will get variables pointing to them nulled by the garbage collector in ProcessObjectArray after they are created again for a load. Here’s what’s happening in another use case that seems related to the issue I reported above:

  1. Save the game.
  2. Player pawn dies
  3. Reload last save point
  4. After reloading the last save point, set a variable in code that points to the new player pawn.
  5. Garbage collector nulls out this variable pointing to the new player pawn.
  6. Player pawn is still very much alive and well in the world???

This seems very odd. Any ideas? Am I at least describing the problem in a way that makes sense?

Are you using C++? Are the variables UPROPERTY?

Yeah, the second example I gave is setting a UPROPERTY value in C++. However, the first example is just referencing components I’ve added to a blueprint in the editor. I’m 99% sure they’re related to the same underlying issue and the first example is probably a lot easier to repro.

Sorry, but I can’t help you then. Need answer from Rama. As you might have noticed, I have some weird issues regarding this plugin as well.

Appreciate you reaching out! Def sounds like you’ve got a couple gnarly issues on your end, as well. I think if you color within the lines using this plugin then everything performs very well, but I’m trying to push the systems to support some of my more complex features and that’s where I’ve been hitting issues.

@Rama you are our only hope! :smiley:

Rama is Back

Sorry folks I was moving home locations here in FL due to a mold issue in my previous residence, so I was away for a while.

Thank you for this!

Great suggestion!

I will implement in my next update which includes my versioning architecture

What is your desired engine version?

:heart:

Rama

Can you give me a specific example so I can understand exactly what you’d like better?

In your code example, why did you make it an interface instead of adding directly to your GameState?

Lovely to hear from you!

Rama

​​​​​​Are you experiencing an issue with that? I tried my hardest to make the Rama Save System as compatible as possible, which means if data exists from an older save I load it, and if new vars were created or new stuff added, I obviously can’t load that data, but the save file will still load whatever it can

I very much look forward to assisting you with this issue, if you still have it, please email me at my marketplace support email:
https://www.unrealengine.com/marketplace/profile/Rama

I would happily discuss here but it sounds rather specific and involved.

:heart:

Rama

Thank you for trying to help [USER=“43607”]Masonic Studios[/USER] while I was away :slight_smile:

:slight_smile:

Rama

Coloring outside the lines definitely requires more communication than coloring within the lines

I think we have hit upon some kind of Natural Law that is generally applicable and might even work well in romantic relationships…

If you can identify what counts as coloring WITHIN the lines from your lady’s perspective, then you have a low-crash-probability environment (LCPE, pronounced El-sip-ee)…

:heart:

Rama

PS: regarding the actual issue, are you setting the pointer synchronously with the ActorFullyLoaded event (the destroy and recreate are synchronous so perhaps a delay of some kind is needed?

This would be an awesome thing to have a repro project of that I could fiddle with in isolation to figure out some kind of solution. Can you repro it easily?

Welcome back Rama!

UE4.19 is fine. We keep sitting on 4.16 for now as we rely on other plugins. But we should be finally able to update to UE4.19.

Thanks you very much, that gives hope we will get this to run at some point. However I will wait until we update to UE4.19. Maybe some magic happens and the issue goes POOF

Regarding saving:
I don’t know if you removed it, but at some point saving on a client was not possible (RamaSaveEngine does not spawn on client). We have a very special case where the client should be able to save. In case the restriction is still existing, can you please add a checkbox to your RamaSaveSettings (Editor) to allow save on client. TargetVersion UE4.19 would be nice.

Cheers.

I’m able to repro my first error very easily in a clean project. Since I believe the two instances might be related, maybe start w/ these repro steps in a clean project and we can go from there? Here they are:

  1. Create a new blueprint class that just has a cube static mesh (so you can see it) and a RamaSaveComponent. Leave default settings on everything.
  2. In the tick function for this new class, just simply call “GetComponentByClass” searching for a Sphere Collision Component and print out the value like I’ve done here. This is simply to demonstrate whether or not there is still a valid pointer to a Sphere Collision Component on this actor (which we will add later…but not yet!).
  3. Place an instance of this new blueprint class in your level by dragging/dropping it into the level.
  4. Add a Sphere Collision Component to this new actor in your level. That is specifically to say, DO NOT add the Sphere Collision Component in the base blueprint class. This bug only surfaces when you add the component AFTER placing it in the level on the actor instance.
  5. Setup some simple events to save/load the level.
  6. Launch the level. You should see a bunch of debug output referencing that Sphere Collision Component.
  7. Save the game. You should still see the debug output.
  8. Load the game. Now, debug output is no longer there because it can’t find the Sphere Collision Component on the actor.

Please let me know if you can’t repro and I’ll just record a video instead :slight_smile: I hope this helps track down the issue! I can try to find clean repro steps for the other instance where this bug popped up, as well.

@Rama just a quick heads up that I tracked down my second issue to something unrelated in my project. This issue just above w/ repro steps is the only problem I’m running into now :slight_smile:

Also, sorry…just recently changed my display name. Sorry if it’s confusing O_o

I just tried to install this to 4.19 and when you click install nothing happens… Something is wrong just want to give Rama a heads up before more people try to use it with 4.19

I can confirm this, it’s happening to me as well. Only on version 4.19, when trying to install the plugin to the engine from the launcher nothing happens. Is there any other way to download the plugin from the marketplace?

I was able to download and install so it should be working now. Thanks Rama

You’re welcome!

:slight_smile:

Rama

I do not currently serialize dynamically added components, you’d have to implement that yourself by saving the class of the component, and the transform, and any properties you thought were important, as ustruct most likely. I am still thinking about the best way to handle dynamically added components, a complex case :slight_smile:

Rama