Forum rules - please read before posting.

Migrating to a custom scene save/restore system (checkpoint/objective-based)

edited April 2020 in Technical Q&A

Hi there,

for several reasons I've been asked to migrate to another save system, one that is somehow able to preserve character progress even if I change room, rename objects, etc.
It's basically a "checkpoint" list that tracks just the relevant events/explored rooms.
It could have easily been done using global vars, but I've been asked to rewrite it from scratch and completely decoupling it from AC as much as possible.

I still don't feel like wiping all the "Remember" scripts from a complete game, so I was wondering if there's any way to hook the scene loading just a moment before "restoring" it using the save system.

I'd love instead to be able to execute my code via scripting only, in place of the default AC behaviour.

I'd still love to leave all OnLoad ActionList/ActionListAssets in place, just in case.

Could you please provide some direction on the hot spots I should be operating to prevent the builtin AC load/save system from executing, and have my code to deal with it?

I know it's an unusual request, but that's what I've been asked and would love to know if it's feasible.

I guess I should be commenting out a few lines in the source files, and maybe hooking to some event that fires after loading the scene and a moment before the builtin loading system triggers.

Now that I think about it, I should probably save other info, like the inventory, in some custom way.

And, write specific code to restore the scene state depending on the active "checkpoins".

I'm really not happy to do it, but I believe I can't avoid it. I already pointed out with the client that she's messing up with the original design, and that's going to be a pain to manually refactor all the scenes like this :neutral:

Comments

  • "Character progress", as in where the Player is, or which scene they're in? That's already recorded in save games - or are you referring to NPCs?

    Are you referring to the all save data (i.e. save files), or just when switching scenes through natural gameplay?

    The upcoming v1.71 release will introduce a new "OnInitialiseScene" event that will be triggered when a scene is initialised, but before any save data is loaded into it.

    When loading a save file, the order of events will then be:

    • OnBeforeLoading (in the original scene)
    • OnInitialiseScene (once in the new scene, if there was a scene change)
    • OnFinishLoading (once loading has finished)
  • Hi Chris!

    By "character progress" I mean saving just the minimum bare data, mostly in the form of a hashmap or list of strings to be encrypted in the playerprefs.

    eg:
    "scene_01_visited"
    "scene_01_puzzle01_solved"
    "scene_02_visited"

    I should not be relying on AC's save system, but transitioning to something different and rewritten from scratch.

    Every time a scene gets loaded, I run my personal routine to restore the scene to its previous saved state, by checking the above "checkpoints", or "completed objectives", or "milestones", if that makes sense.

    this means that no "Remember" script should trigger, as I'm restoring the scene state in a custom way.

    This is because we're going to have some dynamic elements in the puzzles, and we may want to change the whole puzzle without compromising the user progress too much when they receive an update via the Play Store.

    If I change the name of a scene, change the build index or remove/add elements from a scene, the savegame would still work because I'm saving just the minimum info required to reconstruct the player progress, without having to save lesser details or elements that may render the savegame unusable when updating the game.

    I'm probably just tracking a few key actions (puzzle solving, accessing a zone or a scene), and restoring the loaded scene/save according to it.

    Since there's only one hidden "save slot", loading the last scene when pressing "Continue game" or returning to the same scene from another one (as part of the gameplay) doesn't matter. I just check those "milestones" and forcedfully reconstruct item positions/visibility, etc.

    I simply need to not depend on serialization or specific gameobjects.

    I understand that tracking progress in this way could be done via global variables and using no "Remember " scripts, but I'd like to just leave the scenes as they are, and not executing the part of the code of AC that restores the state of a scene when loading it.

    This is... something I'd have avoided, but I've been specifically requested to implement it in this way, for several reasons I can't refuse :/

    So in the previous post was asking how to "hijack" AC's Save/Restore system by surgically touching the whole framework in the quickest focused way, without having to remove Remember scripts or OnLoad events.

  • edited April 2020

    To stop all scene data from being loaded into the scene (whether through natural gameplay, or loading a save file), just add a return statement to the top of the LevelStorage script's ReturnCurrentLevelData method.

  • Thanks Chris!

    that saved me lot of time - I didn't have to manually backtrack to that, without being even sure that was 100% safe to do that - or the right way to do that :)

    So, here's what I did:

    • to avoid refactoring other classes and to keep potential file references I renamed (from the Unity Project View ) LevelStorage to LevelStorage_custom
    • I duplicated it and renamed it to LevelStorage_base
    • I refactored LevelStorage_custom to LevelStorage, and declared it as extending LevelStorage_base (the actual AC original class)
    • I cleaned up LevelStorage, and overrode ReturnCurrentLevelData
    • of course I had to declare a few methods on LevelStorage_base as virtual

    so it's a bit dirty at the moment but I believe I got how it works.

    by having a few LevelStorage methods as virtual I could just:

    public class LevelStorage : LevelStorage_base
    {
        /// <inheritdoc />
        public override void ReturnCurrentLevelData(bool restoringSaveFile)
        {
            AssetLoader.UnloadAssets ();
        }
    }
    

    of course I have to be careful when I update to a new AC version, because LevelStorage would have the same ID as my (subclassed) LevelStorage, but I had to do that to potentially avoid any extra refactoring or data loss/missing script.

    I also saw
    persistentEnginePrefab = (GameObject) Instantiate (Resources.Load (Resource.persistentEngine));

    if that persistentEnginePrefab was somehow public and configurable per-project, that would be easier to just swap a prefab to completely overhaul the save/system!

    I'm now wondering - Maybe I should also stop saving all the level data since I don't need it anymore, right?

  • A similar change to the StoreCurrentLevelData function would be the way to do that.

Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Welcome to the official forum for Adventure Creator.