[HOWTO] How To: Use Corgi / TopDown Engine MMSceneLoadingManager

Announcements, support questions, and discussion for the Dialogue System.
User avatar
Tony Li
Posts: 22104
Joined: Thu Jul 18, 2013 1:27 pm

[HOWTO] How To: Use Corgi / TopDown Engine MMSceneLoadingManager

Post by Tony Li »

If you're using More Mountains' Corgi Engine or TopDown Engine and want to use its MMSceneLoadingManager instead of the Pixel Crusher save system's StandardSceneTransitionManager:
  • Untick the Save System component's Save Current Scene checkbox.
  • If you're using MMSceneLoadingManager/LoadingSceneManager to load a scene on start, make a subclass and override the LoadAsynchronously() coroutine. At the beginning of the coroutine, call:

    Code: Select all

    PixelCrushers.SaveSystem.RecordSavedGameData();
    PixelCrushers.SaveSystem.BeforeSceneChange();
    At the end of the coroutine, call:

    Code: Select all

    PixelCrushers.SaveSystem.ApplySavedGameData();
  • If you're calling LoadingSceneManager.LoadScene manually, you'll need to call

    Code: Select all

    PixelCrushers.SaveSystem.RecordSavedGameData();
    PixelCrushers.SaveSystem.BeforeSceneChange();
    before calling LoadingSceneManager.LoadScene. Also add a script that hooks into SceneManager.sceneLoaded. Example:

    Code: Select all

    using UnityEngine;
    using UnityEngine.SceneManagement;
    public class ApplySaveDataOnSceneLoad : MonoBehaviour
    {
        void Awake() { SceneManager.sceneLoaded += OnLoaded; }
        void OnLoaded(Scene scene, LoadSceneMode mode)
        {
            PixelCrushers.SaveSystem.ApplySavedGameData();
        }
    }
The Pixel Crushers/Common/Third Party Support/TopDown Engine Support package folder contains a prewritten subclass for you. In your LoadingScreen scene, replace the MMLoadingSceneManager component with your subclass. You can replace it in-place.
Peter Drake
Posts: 37
Joined: Tue May 17, 2022 3:49 pm

Re: [HOWTO] How To: Use Corgi / TopDown Engine MMSceneLoadingManager

Post by Peter Drake »

I'm using MM's FinishLevel class, so I'm trying to apply this.

I created a subclass of FinishLevel to attach to my level exit GameObject:

Code: Select all

public class FinishLevelUsingPixelCrusherSaveSystem : FinishLevel
{
    /// <summary>
    /// Loads the next level
    /// </summary>
    public override void GoToNextLevel()
    {
        if (LevelManager.HasInstance)
        {
            LevelManager.Instance.GotoLevel(LevelName);
        }
        else
        {
            MMSceneLoadingManagerUsingPixelCrusherSaveSystem.LoadScene(LevelName); // This line is different
        }
    }
}
The new class I'm calling LoadScene on there is:

Code: Select all

public class MMSceneLoadingManagerUsingPixelCrusherSaveSystem :  MMSceneLoadingManager
{
    protected override IEnumerator LoadAsynchronously()
    {
        PixelCrushers.SaveSystem.RecordSavedGameData();
        PixelCrushers.SaveSystem.BeforeSceneChange();
        yield return base.LoadAsynchronously();
    }
}
(Is that the right way to call a superclass method in an IEnumerator?)

Can you elaborate on what you mean by "hooks into SceneManager.sceneLoaded"? Do you just mean that I have to attach this script to any GameObject in the scene being loaded?

Apologies for my ignorance. The number of things that have to be glued together to produce a Unity game can be overwhelming.
User avatar
Tony Li
Posts: 22104
Joined: Thu Jul 18, 2013 1:27 pm

Re: [HOWTO] How To: Use Corgi / TopDown Engine MMSceneLoadingManager

Post by Tony Li »

Hi,

You're absolutely right. Putting together a complete game is a big undertaking with a lot of moving parts. It's just a matter of tackling it piece by piece. Your subclasses looks perfect.

In your loading screen scene, remember to replace the MMSceneLoadingManager with your custom subclass.
Peter Drake
Posts: 37
Joined: Tue May 17, 2022 3:49 pm

Re: [HOWTO] How To: Use Corgi / TopDown Engine MMSceneLoadingManager

Post by Peter Drake »

I hammered on this for a while, but I kept having to create subclasses of MM classes, which smelled bad, OOP-wise.

I think I found a simpler solution. Simply subclass MM's FinishLevel:

Code: Select all

using MoreMountains.Tools;
using MoreMountains.TopDownEngine;

public class FinishLevelUsingPixelCrusherSaveSystem : FinishLevel
{
    /// <summary>
    /// Loads the next level
    /// </summary>
    public override void GoToNextLevel()
    {
        PixelCrushers.SaveSystem.RecordSavedGameData();
        PixelCrushers.SaveSystem.BeforeSceneChange();
        if (LevelManager.HasInstance)
        {
            LevelManager.Instance.GotoLevel(LevelName);
        }
        else
        {
            MMSceneLoadingManager.LoadScene(LevelName);
        }
        PixelCrushers.SaveSystem.ApplySavedGameData();
    }
}
This seems to work, in that the item in my inventory is still there when I leave and return to the scene. There is one catch: the capacity of the inventory has been reduced from 6 to 1 -- just enough to hold the one item I put in there.

Thoughts?
User avatar
Tony Li
Posts: 22104
Joined: Thu Jul 18, 2013 1:27 pm

Re: [HOWTO] How To: Use Corgi / TopDown Engine MMSceneLoadingManager

Post by Tony Li »

It's fine to subclass FinishLevel, except for two changes:

1. Don't call PixelCrushers.SaveSystem.ApplySavedGameData() in it. TDE loads asynchronously, which means the scene won't be loaded right away, so you shouldn't call ApplySavedGameData() right away.

2. You must subclass MMSceneLoadingManager and, in the LoadingScreen scene, replace MMSceneLoadingManager with your subclass. Since you're calling RecordSavedGameData() in your FinishLevel subclass, you can make your coroutine look like this instead:

Code: Select all

protected override IEnumerator LoadAsynchronously()
{
    yield return base.LoadAsynchronously();
    yield return new WaitForEndOfFrame(); // Let components in newly-loaded scene initialize themselves first. //[FIXED TYPO]
    PixelCrushers.SaveSystem.ApplySavedGameData();
}
Peter Drake
Posts: 37
Joined: Tue May 17, 2022 3:49 pm

Re: [HOWTO] How To: Use Corgi / TopDown Engine MMSceneLoadingManager

Post by Peter Drake »

I'm getting an error message on that.
Attachments
Screen Shot 2022-05-20 at 2.39.36 PM.png
Screen Shot 2022-05-20 at 2.39.36 PM.png (55.78 KiB) Viewed 1913 times
Peter Drake
Posts: 37
Joined: Tue May 17, 2022 3:49 pm

Re: [HOWTO] How To: Use Corgi / TopDown Engine MMSceneLoadingManager

Post by Peter Drake »

Oh, I see. That has to be yield return new WaitForEndofFrame();
Peter Drake
Posts: 37
Joined: Tue May 17, 2022 3:49 pm

Re: [HOWTO] How To: Use Corgi / TopDown Engine MMSceneLoadingManager

Post by Peter Drake »

Nope, the inventory still isn't returning properly. See before and after screenshots attached.
Screen Shot 2022-05-20 at 2.54.48 PM.png
Screen Shot 2022-05-20 at 2.54.48 PM.png (132.24 KiB) Viewed 1913 times
Screen Shot 2022-05-20 at 2.55.13 PM.png
Screen Shot 2022-05-20 at 2.55.13 PM.png (140.93 KiB) Viewed 1913 times
User avatar
Tony Li
Posts: 22104
Joined: Thu Jul 18, 2013 1:27 pm

Re: [HOWTO] How To: Use Corgi / TopDown Engine MMSceneLoadingManager

Post by Tony Li »

Hi,

Thanks for noting the typo. I fixed it in the code above.

For your InventoryEngineSaver components, make sure you've assigned a unique Key to each one (e.g., "MainInventory", "WeaponInventory", etc.). Also set the Player ID. If you're making a single player game, "Player1" is fine. And tick Save Across Scene Changes:
inventoryEngineSaver.png
inventoryEngineSaver.png (21.19 KiB) Viewed 1910 times
Peter Drake
Posts: 37
Joined: Tue May 17, 2022 3:49 pm

Re: [HOWTO] How To: Use Corgi / TopDown Engine MMSceneLoadingManager

Post by Peter Drake »

Okay, I did that.

Now when I return to the scene I do have six inventory slots ... but I don't have the item I picked up previously.
Attachments
Screen Shot 2022-05-20 at 5.33.49 PM.png
Screen Shot 2022-05-20 at 5.33.49 PM.png (65.5 KiB) Viewed 1909 times
Post Reply