I have found an algorithm that is working well to restore transforms’ attachment parent on load.
This is a long-time issue I couldn’t figure out how to do without making the loading performance a slug.
I couldn’t find previously a way to restore them without assuming the parent Actor still exists, but the new code seems to work fine for that;
If there’s no parent, transforms are now registered in world space, otherwise plugin now records a transform relative to parent.
I’m submitting update 2.9.5 with this change, for Unreal 4.25.
I’m new to the Savior plugin overall, though have bought it quite time ago but haven’t got time to dig into it. It looks like a really powerful tool, but I have trouble getting into it since I’m a BP-only guy.
I’ve tried saving/loading a level and the system itself seems to work in a way, but the loaded level appears all messed up - enemy actors are in wrong places after loading and their healthbar widgets (done via child actor components) appear in random places too. I know there are no videos available, but is there any guide of any kind available in text form with a summary of what needs to be done to get the system working?
Child Actor Components are not directly supported, you should add “!Tran” actor tag to them to ignore their transform on load.
The plugin considers normal transforms only when loading, child actor transforms are a bunch of hackery, when loading transform the plugin doesn’t check if actor is a child actor component or not.
Thanks, that solved it for a health bar, but enemies are still spawned randomly and my pickups are merged to one place on load. Can you please advise what could be the cause?
I can see the enemies get spawned and then thrown randomly behind the blurred save/load screen from your HUD
EDIT: My enemies and pickups so far are set on the level permanently, not created on runtime
Your Actors are missing a Guid property named ‘SGUID’ (save global unique identifier).
If you don’t have a SGUID with a valid value for your classes, the plugin thinks every instance are all the same actor. Add the ID to your Blueprint class and generate a unique value (for each instance).
I see. Can you please advise what is the correct setup for pickups in this case? I mean the ones that should be respawned if player died between saves. In this case it gets marked by “Mark Destroyed” function and destroyed on load, but the player’s properties that were changed on item pickup are reverted also
That’s not exactly the case here. I meant this scenario: player saves -> player picks up the pickup (say sword), its properties (damage, armor, etc.) are now stored in player’s property (struct type) “Slot1” -> pickup gets “Mark Destroyed” and now is set for destruction on next load by your system -> player gets killed and loads the save -> his struct “Slot1” is reverted to the last save (without the pickup) and there’s no pickup to pick up
Also I’ve hit some strange behavior - I’ve implemented all 3 necessary steps including SGUID into my player character, but struct type values won’t load properly but ints, strings, books, etc. load ok. Is there something different when dealing with structs? I’ve set all variables inside struct to SaveGame. EDIT: Nevermind this, it was a different issue, structs are saving properly
What you describe about auto destroy to me sounds like it’s doing it’s meant to do.
The pickup marked destroyed will self-destroy on save load…
Btw, If you ever fall into necessity of using multiple load functions, for whatever reason, make sure you use a node to check for “Thread Safety” of the save system.
I have seem devs using async load, and use a second load node, and a third one, while the load process of the first one is still running (as a background task).
Pretty crazy stuff some people are doing.
Yeah, the system works as intended in this case. I meant maybe there’s an “official” way of handling pickups restoring in this case so the player will still has the initial flow unbroken (from the top of my mind - a list of destroyed objects that are marked as destroyed only on the next save, so they will be respawned as usual during this and next save), but I’ll figure something out
Thanks for the tip, will be on the lookout for that. Speaking of crazy stuff… I guess I’ll need your advise on this one too: I need to save co-op players pairs in a game and load them only for specific players, the ones that initially were playing in this particular pair, so these particular players will get this own progression save. So far I have no idea how to do this from the perspective of saving, maybe you’ve encountered this case before? Should I save game to slots on both LS and client? (which makes sense to me since the next time LS could be the client and vice versa)
I would do a setup in game mode with important data there and save using “Save Game Mode” node.
Then sync client to loaded data when connected… if you save on both, you could load outdated file on one of them and you will have to sync them anyway.
Hm, sounds like a plan. I’ll have to dig deeper into Game Modes, so far I’m not so confident with it in terms of multiplayer. But I guess I should also save players actors as well? Or stuff like currencies, skills unlocked by players and so are better fit in Game Mode?
I’m back with a couple of questions if you don’t mind (pardon for such a concentration of newbie points in one post):
what is the correct (intended) scenario for saving with pause? When saving from under the charBP I have to set TickWhenPaused flag on the char and that eliminates the whole point of setting game on pause during save/load
I tried to set up the game mode saving/loading as you advised, but so far I can’t get my charBP to save, do I need to set up something additional? (when using save/load GameWorld nodes everything is correct)
my main scenario for Savior usage is saving/loading of single and pair progression in a roguelike and transferring them from the previous level to the next one. Since I’m not in any way an architectural guru I’m having trouble applying saved info on top of the spawned charBPs - I should do it after connecting and spawning both players on the level, but before BeginPlay, right?
Something in engine might have been charged when running save as a task while paused. It shouldn’t be affected by that. I have to check that later.
Your charBP should always spawn with the same SGUID value. For a main character I just use an invalidated Guid value (0000-0000-0000-0000). And I do not use on it a Guid generator in constructor.
You can use “Load Game Mode” at any time, but you probably need some extra loading screen setup to load saves after BeginPlay to make sure all default values have already initialized before loading.