Page 1 of 2
[HOWTO] How To: Use Corgi / TopDown Engine MMSceneLoadingManager
Posted: Mon Feb 21, 2022 4:58 pm
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.
Re: [HOWTO] How To: Use Corgi / TopDown Engine MMSceneLoadingManager
Posted: Fri May 20, 2022 2:45 pm
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.
Re: [HOWTO] How To: Use Corgi / TopDown Engine MMSceneLoadingManager
Posted: Fri May 20, 2022 3:10 pm
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.
Re: [HOWTO] How To: Use Corgi / TopDown Engine MMSceneLoadingManager
Posted: Fri May 20, 2022 4:36 pm
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?
Re: [HOWTO] How To: Use Corgi / TopDown Engine MMSceneLoadingManager
Posted: Fri May 20, 2022 4:56 pm
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();
}
Re: [HOWTO] How To: Use Corgi / TopDown Engine MMSceneLoadingManager
Posted: Fri May 20, 2022 5:41 pm
by Peter Drake
I'm getting an error message on that.
Re: [HOWTO] How To: Use Corgi / TopDown Engine MMSceneLoadingManager
Posted: Fri May 20, 2022 5:52 pm
by Peter Drake
Oh, I see. That has to be yield return new WaitForEndofFrame();
Re: [HOWTO] How To: Use Corgi / TopDown Engine MMSceneLoadingManager
Posted: Fri May 20, 2022 5:56 pm
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 (132.24 KiB) Viewed 1921 times
- Screen Shot 2022-05-20 at 2.55.13 PM.png (140.93 KiB) Viewed 1921 times
Re: [HOWTO] How To: Use Corgi / TopDown Engine MMSceneLoadingManager
Posted: Fri May 20, 2022 8:25 pm
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 (21.19 KiB) Viewed 1918 times
Re: [HOWTO] How To: Use Corgi / TopDown Engine MMSceneLoadingManager
Posted: Fri May 20, 2022 8:34 pm
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.