Forum begins after the advertisement:
[Part 7] Updating the Map
Home › Forums › Video Game Tutorial Series › Creating a Metroidvania in Unity › [Part 7] Updating the Map
- This topic has 27 replies, 3 voices, and was last updated 1 hour, 45 minutes ago by
Sean Ng.
-
AuthorPosts
-
May 24, 2026 at 9:01 am #19655::
My map is only setting map of the first scene to active in the map ui. I tried using debug.log to find out if any of the functions were not running but everything seems to be running fine. However, I’m not sure if gamemanager.savescene and savedata.initialize is only supposed to work at the beginning and not everytime a new scene is opened. Here are the scripts.
using System.Collections; using System.Collections.Generic; using UnityEngine; using System.IO; using UnityEngine.SceneManagement; [System.Serializable] public struct SaveData { public static SaveData Instance; //mapstuff public HashSet<string> sceneNames; public void Initialize() { if (sceneNames == null) { sceneNames = new HashSet<string>(); Debug.Log("SaveData successful"); } } }using System.Collections; using System.Collections.Generic; using UnityEngine; public class MapManager : MonoBehaviour { [SerializeField] GameObject[] maps; Bench bench; private void OnEnable() { bench = FindObjectOfType<Bench>(); if(bench != null) { if(bench.interacted) { UpdateMap(); Debug.Log("Map updated"); } } } void UpdateMap() { var savedScenes = SaveData.Instance.sceneNames; for (int i = 0; i < maps.Length; i++) { if(savedScenes.Contains("Tundra_"+(i + 1))) { maps[i].SetActive(true); Debug.Log("Map Set True"); } else { maps[i].SetActive(false); } } } }using UnityEngine; using UnityEngine.SceneManagement; public class GameManager : MonoBehaviour { public static GameManager Instance { get; private set; } public string transitionedFromScene; public Vector2 platformingRespawnPoint; public Vector2 respawnPoint; private Bench bench; public GameObject shade; private void Awake() { SaveData.Instance.Initialize(); if (Instance != null && Instance != this) { Destroy(gameObject); return; } SaveScene(); Instance = this; DontDestroyOnLoad(gameObject); } public void SaveScene() { string currentSceneName = SceneManager.GetActiveScene().name; SaveData.Instance.sceneNames.Add(currentSceneName); Debug.Log("GameManager successful"); } public void RespawnPlayer() { if (bench != null && bench.interacted) { respawnPoint = bench.transform.position; } else { respawnPoint = platformingRespawnPoint; } if (PlayerController.Instance != null) { PlayerController.Instance.transform.position = respawnPoint; PlayerController.Instance.Respawn(); } StartCoroutine(UIManager.Instance.DeactivateDeathScreen()); } private void OnEnable() { SceneManager.sceneLoaded += OnSceneLoaded; } private void OnDisable() { SceneManager.sceneLoaded -= OnSceneLoaded; } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { bench = FindObjectOfType<Bench>(); } }May 24, 2026 at 10:06 pm #19657::I remember you already have the project on GitHub right? Can you make sure your project is updated onto it, then repost the link here?
May 25, 2026 at 9:34 am #19658May 25, 2026 at 11:03 am #19659::Hi nirvik, can you add me as collaborator for the project to help as it is privated
- 1 anonymous person
May 25, 2026 at 9:34 pm #19673May 26, 2026 at 12:14 pm #19676::Your project folder on github is not up to date as there is no MapManager script, MapUI and GameManager not updated, can you push what you currently have that way I can pull find where the problem is.
May 26, 2026 at 8:17 pm #19683May 27, 2026 at 1:29 pm #19688::The fix for this will only need to change the GameManager script, it will be abit different from tutorial but it is just rearranging. In
GameManager.cswe will moveSaveScene()fromAwake()toOnSceneLoaded().using UnityEngine; using UnityEngine.SceneManagement; public class GameManager : MonoBehaviour { public static GameManager Instance { get; private set; } public string transitionedFromScene; public Vector2 platformingRespawnPoint; public Vector2 respawnPoint; private Bench bench; public GameObject shade; private void Awake() { SaveData.Instance.Initialize(); if (Instance != null && Instance != this) { Destroy(gameObject); return; } SaveScene(); Instance = this; DontDestroyOnLoad(gameObject); } public void SaveScene() { string currentSceneName = SceneManager.GetActiveScene().name; Debug.Log("Saved " + currentSceneName); SaveData.Instance.sceneNames.Add(currentSceneName); } public void RespawnPlayer() { if (bench != null && bench.interacted) { respawnPoint = bench.transform.position; } else { respawnPoint = platformingRespawnPoint; } if (PlayerController.Instance != null) { PlayerController.Instance.transform.position = respawnPoint; PlayerController.Instance.Respawn(); } StartCoroutine(UIManager.Instance.DeactivateDeathScreen()); } private void OnEnable() { SceneManager.sceneLoaded += OnSceneLoaded; } private void OnDisable() { SceneManager.sceneLoaded -= OnSceneLoaded; } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { bench = FindObjectOfType<Bench>(); SaveScene(); Debug.Log("Found bench and saved map details"); } }It doesn’t work currently as
Awake()is only called once and since it doesn’t destroy when loading next scene it won’t be called again preventingSavescene()from being called, with this changeSaveScene()will always be called when changing scene.May 28, 2026 at 4:52 am #19689::thank you that worked, but now I am having problems with the player spawning. I have updated github again https://github.com/KingPloof393/Metroidvania-Prototype Also is there a way to delete the save data
May 28, 2026 at 5:07 am #19690::I have fixed the problem I was having earlier but the only problem now is that the player is spawning at the entrance to the scene and the mana state is not bein saved github is updated https://github.com/KingPloof393/Metroidvania-Prototype
May 28, 2026 at 10:33 am #19693::the original error is back. EndOfStreamException: Unable to read beyond the end of the stream. System.IO.BinaryReader.ReadByte () (at <4a4789deb75f446a81a24a1a00bdd3f9>:0) System.IO.BinaryReader.Read7BitEncodedInt () (at <4a4789deb75f446a81a24a1a00bdd3f9>:0) System.IO.BinaryReader.ReadString () (at <4a4789deb75f446a81a24a1a00bdd3f9>:0) SaveData.LoadShadeData () (at Assets/Scripts/SaveData.cs:156) GameManager.OnSceneLoaded (UnityEngine.SceneManagement.Scene scene, UnityEngine.SceneManagement.LoadSceneMode mode) (at Assets/Scripts/GameManager.cs:77) UnityEngine.SceneManagement.SceneManager.Internal_SceneLoaded (UnityEngine.SceneManagement.Scene scene, UnityEngine.SceneManagement.LoadSceneMode mode) (at <f712b1dc50b4468388b9c5f95d0d0eaf>:0)
EndOfStreamException: Unable to read beyond the end of the stream. System.IO.BinaryReader.FillBuffer (System.Int32 numBytes) (at <4a4789deb75f446a81a24a1a00bdd3f9>:0) System.IO.BinaryReader.ReadInt32 () (at <4a4789deb75f446a81a24a1a00bdd3f9>:0) SaveData.LoadPlayerData () (at Assets/Scripts/SaveData.cs:107) PlayerController.Start () (at Assets/Scripts/PlayerController.cs:156)
May 28, 2026 at 10:41 am #19694::I am abit confused with what problem your running into, I have pulled the lastest version and when testing after going to a new scene then saving on the bench I stop then start the simulation, I spawn at the bench of the scene I last saved, the amount of mana also remain the same when restarting the simulation.
May 28, 2026 at 11:23 am #19695::The console error you pasted is related to the shade it should not break the game, I am still able to play and the player is spawned at the last bench position, the reason why this error code appears is because there is no shade in the game,
SaveData.cscreates a empty file save.shade.data, but it has nothing inside causing the error to appear as the code knows the file exist but trying to access information that don’t exist within the file it throws out the error.If you don’t want to see the error
SaveData.cschange the LoadShadeData and add a ClearShadedatapublic void LoadShadeData() { FileInfo shadeInfo = new FileInfo(Application.persistentDataPath + "/save.shade.data"); if (shadeInfo.Exists && shadeInfo.Length != 0) { using (BinaryReader reader = new BinaryReader(File.OpenRead(Application.persistentDataPath + "/save.shade.data"))) { sceneWithShade = reader.ReadString(); shadePos.x = reader.ReadSingle(); shadePos.y = reader.ReadSingle(); float rotationX = reader.ReadSingle(); float rotationY = reader.ReadSingle(); float rotationZ = reader.ReadSingle(); float rotationW = reader.ReadSingle(); shadeRot = new Quaternion(rotationX, rotationY, rotationZ, rotationW); } } else { Debug.Log("Shade Doesn't Exist"); } } public void ClearShadeData() { if (File.Exists(Application.persistentDataPath + "/save.shade.data")) { File.Create(Application.persistentDataPath + "/save.shade.data").Close(); Debug.Log("shade data cleared"); } } }Shade.csat the death functionprotected override void Death(float _destroyTime) { rb.gravityScale = 12; SaveData.Instance.ClearShadeData(); base.Death(_destroyTime); }May 28, 2026 at 11:37 am #19696::whenever I start the game the player just hovers in the jumping animation cannot jump. Additionally it displays full mana despite not being having 0 mana. Also for the mana problem it is not switching to the half mana state. Thank you for the help with the shade though
May 28, 2026 at 11:53 am #19697May 28, 2026 at 12:29 pm #19698::Okay I now know why, before I do that can you update the shade error based on what I typed in above I edited the message again as the code I gave earlier is not well written.
The reason why your player is stuck is due to how you delete the save data, I am guessing you went to the save file within and removed everything that was inside, this is the same error with the shade of code trying to access something that doesn’t exist.
SaveData.csLoadPlayerData functionpublic void LoadPlayerData() { FileInfo playerInfo = new FileInfo(Application.persistentDataPath + "/save.player.data"); if (playerInfo.Exists && playerInfo.Length != 0) { using (BinaryReader reader = new BinaryReader(File.OpenRead(Application.persistentDataPath + "/save.player.data"))) { playerHealth = reader.ReadInt32(); playerMana = reader.ReadSingle(); playerHalfMana = reader.ReadBoolean(); playerPosition.x = reader.ReadSingle(); playerPosition.y = reader.ReadSingle(); lastScene = reader.ReadString(); SceneManager.LoadScene(lastScene); PlayerController.Instance.transform.position = playerPosition; PlayerController.Instance.halfMana = playerHalfMana; PlayerController.Instance.Health = playerHealth; PlayerController.Instance.Mana = playerMana; Debug.Log(playerHalfMana); } } else { Debug.Log("File Doesnt Exist"); PlayerController.Instance.halfMana = false; PlayerController.Instance.health = PlayerController.Instance.maxHealth; PlayerController.Instance.Mana = 0; } }also another thing I’ve notice is the half mana won’t be half if you just reload the game to fix this within
PlayerController.csvoid Start() { pState = GetComponent<PlayerStateList>(); rb = GetComponent<Rigidbody2D>(); sr = GetComponent<SpriteRenderer>(); anim = GetComponent<Animator>(); SaveData.Instance.LoadPlayerData(); gravity = rb.gravityScale; Health = maxHealth; if (halfMana) { CutMana(); } Mana = mana; manaStorage.fillAmount = Mana; } public void Respawn() { if(!pState.alive) { pState.alive = true; CutMana(); Mana = 0; Health = maxHealth; anim.Play("Player_Idle"); rb.constraints &= ~RigidbodyConstraints2D.FreezePositionX; SaveData.Instance.SavePlayerData(); } } public void CutMana() { halfMana = true; UIManager.Instance.SwitchMana(UIManager.ManaState.HalfMana); }May 28, 2026 at 10:27 pm #19700::that fixed most of the problems but whenever I die in the second scene even when I have saved at a bench it still spawns me at the entrance to the scene I have also updated github https://github.com/KingPloof393/Metroidvania-Prototype
May 28, 2026 at 11:32 pm #19701::This bug only happen when you enter a scene and saved on a bench then die in the same scene, when you respawn you reload the same scene which cause sceneTransitions to be spawned again, this cause them to run their
Start()function, your GameManager on the other hand is not spawned again whenever you load a new scene.As your GameManager still have the scene they were transitioned from saved, when you respawn you spawn at the bench then moved to the transition to reply the sceneTransition, for this fix we will clear
GameManager.cs transitionedFromSceneafter the transition start playing so if you die again it won’t take it as if you were entering from a previous scene.SceneTransition.csprivate void Start() { if(GameManager.Instance.transitionedFromScene == transitionTo) { PlayerController.Instance.transform.position = startPoint.position; PlayerController.Instance.pState.cutscene = true; PlayerController.Instance.pState.invincible = true; StartCoroutine(PlayerController.Instance.WalkIntoNewScene(exitDirection, exitTime)); GameManager.Instance.transitionedFromScene = null; } StartCoroutine(UIManager.Instance.sceneFader.Fade(SceneFader.FadeDirection.Out)); }May 29, 2026 at 12:07 am #19702May 29, 2026 at 12:39 am #19703::I have found that the player spawning at the entrance only occurs if the player saves at a bench in one scene leaves the scene returns and dies. I hope this helps.
-
AuthorPosts
- You must be logged in to reply to this topic.
Advertisement below: