Saving Quest Journal without using Portal or SaveSystem.LoadScene call

Announcements, support questions, and discussion for Quest Machine.
Post Reply
jlhacode
Posts: 77
Joined: Fri Jul 03, 2020 6:23 am

Saving Quest Journal without using Portal or SaveSystem.LoadScene call

Post by jlhacode »

Hi, I want to persist quest status between a scene change. It's important to note that my current implementation is using TopDown Engine's GoToLevelEntryPoint script to load scenes.

I tried using the implementation from this post https://www.pixelcrushers.com/phpbb/vie ... f=9&t=2624 but it seems that I need to now use Portals or a SaveSystem.LoadScene call, which would require me to refactor pretty much all of my scene transitions.

Is there was a way to persist Quest state in a way that's more friendly with TDE's GoToLevelEntryPoint script?
User avatar
Tony Li
Posts: 22108
Joined: Thu Jul 18, 2013 1:27 pm

Re: Saving Quest Journal without using Portal or SaveSystem.LoadScene call

Post by Tony Li »

Hi,

Here are two methods. The first only saves the quest journal. The second uses the full Quest Machine save system, which allows you to save the info on quest givers, spawners, etc., as well as the full set of save system savers (DestructibleSaver, ActiveSaver, PositionSaver, etc.).

Method 1:
Before leaving the old scene, get the quest journal data as a string:

Code: Select all

string s = yourQuestJournal.RecordData();
After loading the new scene, apply the saved data to the quest journal in the new scene:

Code: Select all

string s = yourOtherQuestJournal.ApplyData(s);
I'll skip the details since you'll probably want to go with method 2:

Method 2:
Set up Quest Machine's Save System as indicated in the save system manual. (GameObject with SaveSystem and JsonDataSerializer components. Untick the Save System component's Save Current Scene checkbox if you'll use TDE to save/load the player into the right scene.)

Before changing scenes, call PixelCrushers.SaveSystem.BeforeSceneChange() and RecordSavedGameData().

After loading the new scene, call PixelCrushers.SaveSystem.ApplySavedGameData().

For example, make a subclass of GoToLevelEntryPoint and override GoToNextLevel:

Code: Select all

public GoToNextEntryPointWithSave : GoToNextEntryPoint
{
    public override void GoToNextLevel()
    {
        PixelCrushers.SaveSystem.OnBeforeSceneChange();
        PixelCrushers.SaveSystem.RecordSavedGameData();
        base.GoToNextLevel ();
    }
}
Make a subclass of LoadingSceneManager that overrides LoadingComplete:

Code: Select all

public class LoadingSceneManagerWithSave : LoadingSceneManager
{
    protected override void LoadingComplete()
    {
        base.LoadingComplete();
        PixelCrushers.SaveSystem.ApplySavedGameData();
    }
}

Saved Games
You'll probably also want to include this info in TDE saved games. To save:

Code: Select all

using PixelCrushers; // (Saves having to type the namespace below.)
string s = SaveSystem.Serialize(SaveSystem.RecordSavedGameData());
MMSaveLoadManager.Save(s, fileName, folderName);
To load:

Code: Select all

string s = (string)MMSaveLoadManager.Load(typeof(string), fileName, folderName);
SaveSystem.ApplySavedGameData(SaveSystem.Deserialize<SavedGameData>(s));
jlhacode
Posts: 77
Joined: Fri Jul 03, 2020 6:23 am

Re: Saving Quest Journal without using Portal or SaveSystem.LoadScene call

Post by jlhacode »

Thanks for the quick response.

I implemented the solutions that you recommended, but it seems like the quests aren't persisting in my journal across scene changes still.

I've attached some photos of my scene setup + debug logs.

P.S. I've been banging my head on this problem for about 3 days. I really appreciate you helping out!
Attachments
Screen Shot 2020-07-21 at 7.10.43 PM.png
Screen Shot 2020-07-21 at 7.10.43 PM.png (99.73 KiB) Viewed 1004 times
Screen Shot 2020-07-21 at 7.11.25 PM.png
Screen Shot 2020-07-21 at 7.11.25 PM.png (61.01 KiB) Viewed 1004 times
Screen Shot 2020-07-21 at 7.11.04 PM.png
Screen Shot 2020-07-21 at 7.11.04 PM.png (64.31 KiB) Viewed 1004 times
Last edited by jlhacode on Wed Jul 22, 2020 2:51 pm, edited 1 time in total.
User avatar
Tony Li
Posts: 22108
Joined: Thu Jul 18, 2013 1:27 pm

Re: Saving Quest Journal without using Portal or SaveSystem.LoadScene call

Post by Tony Li »

Hi,

On the Quest Journal component (in both scenes), have you ticked Save Settings > Include In Saved Game Data and Save Across Scene Changes? Is the Save Key the same in both scenes?

Also, try ticking the Save System's Debug checkbox to get more info in the Console.

What code are you using to tie into the save system?

(I'm finishing up work for the night, but I'll check back in the morning.)
jlhacode
Posts: 77
Joined: Fri Jul 03, 2020 6:23 am

Re: Saving Quest Journal without using Portal or SaveSystem.LoadScene call

Post by jlhacode »

Yep, both Include in Saved Game Data and Save Across Scene Changes are checked in the quest journal instances. The quest journal lives on my Player prefab, and the Player prefab gets instantiated via TDE's LevelManager.
What code are you using to tie into the save system?
I'm using the GoToNextEntryPointWithSave and LoadingSceneManagerWithSave code snippets you posted earlier in this thread. Unless you mean something else?
User avatar
Tony Li
Posts: 22108
Joined: Thu Jul 18, 2013 1:27 pm

Re: Saving Quest Journal without using Portal or SaveSystem.LoadScene call

Post by Tony Li »

You may need to wait one frame for TDE's LevelManager to instantiate the player prefab before trying to restore its saved data. Otherwise the player won't be present to receive the saved data.

Code: Select all

public class LoadingSceneManagerWithSave : LoadingSceneManager
{
    protected override void LoadingComplete()
    {
        base.LoadingComplete();
        StartCoroutine(ApplySaveDataAfterPlayerAppears());
    }
    
    IEnumerator ApplySaveDataAfterPlayerAppears()
    {
        // Wait for the end of the next frame to allow LevelManager to instantiate the player first:
        yield return null;
        yield return new WaitForEndOfFrame();
        
        // Then apply saved game data to the player:
        PixelCrushers.SaveSystem.ApplySavedGameData();
    }
}
jlhacode
Posts: 77
Joined: Fri Jul 03, 2020 6:23 am

Re: Saving Quest Journal without using Portal or SaveSystem.LoadScene call

Post by jlhacode »

Hi Tony,

I solved the issue by moving the PixelCrushers.SaveSystem.ApplySavedGameData() from the LoadingSceneManager to the Start() in my Player script. I know this introduces a scene dependency on my player, but I'm willing to live with it.

As a professional (non-unity) developer, I don't understand how one person can possess the time to support so many users. Thank you so much for your help Tony.
User avatar
Tony Li
Posts: 22108
Joined: Thu Jul 18, 2013 1:27 pm

Re: Saving Quest Journal without using Portal or SaveSystem.LoadScene call

Post by Tony Li »

Hi,

It'll still work if you play the gameplay scene directly without coming from whatever menu scene contains your primary copy of the Save System GameObject/component. It'll create a temporary Save System GameObject with no data, so SaveSystem.ApplySavedGameData() won't do anything (and won't cause any problems).

I have the good fortune to be able to develop and support these assets full time, and I'm glad they can give devs a head start on their games. Some days it takes me a little longer to reply to everyone, but I always try to reply as promptly as I can.
Post Reply