Forum begins after the advertisement:
[Part 7] Map problem
Home › Forums › Video Game Tutorial Series › Creating a Metroidvania in Unity › [Part 7] Map problem
- This topic has 70 replies, 4 voices, and was last updated 2 months, 4 weeks ago by MI NI.
-
AuthorPosts
-
August 5, 2024 at 12:05 am #15486::
Oh, I think I forgot to delete the code in GameManager. I will get back to you after testing it.
August 5, 2024 at 12:16 am #15488::After I tested it I think it got a little complicated and I don’t know how to explain it. If you need me to do more testing, I’ll be happy to oblige
August 5, 2024 at 12:28 am #15489::Hmm… Okay this is getting nowhere, can you quickly do a search through all your scripts by pressing “Control + F” then selecting the dropdown menu below the searchbar and selecting “Current Project” from “Current Document”.
Then Search for “scenenames”. Afterwards, can you tell me only instances of
sceneNames
specifically you see.Not the code that have scene names as part of the full name but instead the lines that call
sceneNames
the variable.This is because i just need to confirm that it’s only between
SaveScene()
in GameManager.cs and the variable itself in SaveData.cs. If it is. I recommend we try redoing that code by removing, and rewriting the code again later.August 5, 2024 at 12:43 am #15490August 5, 2024 at 1:12 am #15491::Yep, that’s right. So we can confirm that everything is only between SaveData.cs and GameManager.cs but your code is perfectly fine. Can you help me check one thing. This time you need only just walk between scenes.
You can remove the previous print codes i asked you to put and put this instead in GameManager.cs
public void SaveScene() { //獲取當前場景名稱 var count = string.Join(", ", SaveData.Instance.sceneNames); print(count); print(SaveData.Instance.sceneNames.Count); string currentSceneName = SceneManager.GetActiveScene().name; SaveData.Instance.sceneName.Add(currentSceneName); Debug.Log("saved" + currentSceneName); var count = string.Join(", ", SaveData.Instance.sceneNames); print(count); print(SaveData.Instance.sceneNames.Count); }
This is likely the only area of code where the
sceneNames
are deleted and stays the same. We’re checking if thesceneNames
here are actually deleted, then counting the number of elements in the hashset to check if that number stays the same or increases when we add and we simply just arent printing things correctly.August 5, 2024 at 1:28 am #15492August 5, 2024 at 1:35 am #15493::Your scene data is resetting everytime you enter a scene. May i affirm that in your scene, you do not have a game object that you placed the SaveData script onto right?
August 5, 2024 at 10:16 am #15495::I checked all my game objects and made sure none placed SaveData.cs But I would like to ask, when there are a large number of game objects, is there a way to know which objects use this script?
August 5, 2024 at 10:20 am #15496::In the Scene Hierarchy search bar you can use “t:” followed by the name of the component you are looking for to see all objects that contain said component.
For instance you can use: “t:button” to find all objects that contain a button component, “t:boxcollider2d” to find all box collider 2d’s in the scene. “t:gamemanager” to find all objects with the GameManager script. or “t:savedata” to find savedata scripts.
August 5, 2024 at 10:30 am #15497::Thanks for your tutorial, I used t:SaveData and double-checked that I did not place SaveData.cs in any game object
August 5, 2024 at 2:23 pm #15500::MI NI, can you try changing the
SaveData
object to be aclass
instead of astruct
. See if it fixes the issue.August 5, 2024 at 3:04 pm #15501August 5, 2024 at 5:49 pm #15502::After looking through your project i’ve found the issue.
Disappointingly, It had slipped my mind to not realize that your code was slightly different from ours. It’s the inclusion of this piece of code:
public void Initialize() //ªì©l¤Æ { if (!File.Exists(Application.persistentDataPath + "/save.scenes.data")) { using (BinaryWriter writer = new BinaryWriter(File.Create(Application.persistentDataPath + "/save.scenes.data"))) { writer.Write(0); // Write an empty scene data structure } } LoadSceneData(); } public void SaveSceneData() { using (BinaryWriter writer = new BinaryWriter(File.OpenWrite(Application.persistentDataPath + "/save.scenes.data"))) { writer.Write(sceneName.Count); foreach (string sceneName in sceneName) { writer.Write(sceneName); } } } public void LoadSceneData() { if (File.Exists(Application.persistentDataPath + "/save.scenes.data")) { using (BinaryReader reader = new BinaryReader(File.OpenRead(Application.persistentDataPath + "/save.scenes.data"))) { int sceneCount = reader.ReadInt32(); sceneName = new HashSet<string>(); for (int i = 0; i < sceneCount; i++) { string _sceneName = reader.ReadString(); sceneName.Add(_sceneName); } } } else { sceneName = new HashSet<string>(); } }
The thing is, we did not actually implement a way to save the scene names like we do player data and i had also forgotten to add that in for the series. So these 2 methods were unfamiliar yet i thought they were normal.
In any case, what the issue is, your
LoadSceneData()
is being called inInitialize
. The issue with that is the fact that your GameManager.cs calls your SaveData.csInitialize()
method inAwake()
.Thus every scene you enter, your SaveData.cs will call
LoadSceneData()
.The real problem comes due to the fact that you have no way of calling
SaveSceneData()
. Meaning, that yoursceneNames
data, that you load throughLoadSceneData()
every time you enter a scene, is empty. Thereby causing yoursceneNames
to be null everytime you enter a new scene and thus causing your maps to never progress.
If you want to keep your methods, since they will be good in saving your data, you should just remove that one call for
LoadSceneData()
inInitialize()
, I marked it above, and also look towards callingSaveSceneData()
andLoadSceneData()
somewhere else more appropriate, like in yourSavePlayerData()
.August 5, 2024 at 9:08 pm #15503::After modifying the LoadSceneData();, it worked, but I found that after restarting the game, the map resets. I tried moving SaveSceneData() and LoadSceneData() into SavePlayerData() but it doesn’t work. I want to know how I should modify it to be successful.
<code>using System.Collections; using System.Collections.Generic; using UnityEngine; using System.IO; using UnityEngine.SceneManagement; [System.Serializable] public struct SaveData { public static SaveData Instance; //map stuff public HashSet<string> sceneName; //savePoint stuff public string savePointSceneName; public Vector2 savePointPos; //player stuff public float playerHealth; public float playerMana; public Vector2 playerPosition; public string lastScene; //player skill public bool playerUnlockWallJump; public bool playerUnlockDash; public bool playeUnlockAirJump; public bool playerUnlockSideSpell; public void Initialize() //初始化 { if (!File.Exists(Application.persistentDataPath + "/save.scenes.data")) { using (BinaryWriter writer = new BinaryWriter(File.Create(Application.persistentDataPath + "/save.scenes.data"))) { writer.Write(0); // Write an empty scene data structure } //LoadSceneData(); } //檢查重生點文件是否存在,否則將建立一個新文件 if (!File.Exists(Application.persistentDataPath + "/save.savePoint.data")) { BinaryWriter writer = new BinaryWriter(File.Create(Application.persistentDataPath + "/save.savePoint.data")); } //檢查玩家文件是否存在,否則將建立一個新文件 if (!File.Exists(Application.persistentDataPath + "/save.player.data")) { BinaryWriter writer = new BinaryWriter(File.Create(Application.persistentDataPath + "/save.player.data")); } if (sceneName == null) //檢查此場景是否為空 { //如果是,建立一個新HashSet sceneName = new HashSet<string>(); } } public void SavedSavePoint() { using (BinaryWriter writer = new BinaryWriter(File.OpenWrite(Application.persistentDataPath + "/save.savePoint.data"))) { Debug.Log("SavedSavePoint by SaveData.cs"); writer.Write(savePointSceneName); writer.Write(savePointPos.x); writer.Write(savePointPos.y); } } public void LoadSavePoint() { //if(File.Exists(Application.persistentDataPath + "/save.savePoint.data")) string savePath = Application.persistentDataPath + "/save.savePoint.data"; if(File.Exists(savePath) && new FileInfo(savePath).Length > 0) { using (BinaryReader reader = new BinaryReader(File.OpenRead(Application.persistentDataPath + "/save.savePoint.data"))) { Debug.Log("LoadSavePoint by SaveData.cs"); savePointSceneName = reader.ReadString(); savePointPos.x = reader.ReadSingle(); savePointPos.y = reader.ReadSingle(); } } else { Debug.Log("SavePoint do not exits by SaveData.cs"); } } public void SavePlayerData() //備註:存儲的順序需與讀取的順序相同,否則可能出錯 { using (BinaryWriter writer = new BinaryWriter(File.OpenWrite(Application.persistentDataPath + "/save.player.data"))) { //血量、魔力 playerHealth = PlayerController.Instance.Health; writer.Write(playerHealth); playerMana = PlayerController.Instance.Mana; writer.Write(playerMana); //技能 playerUnlockWallJump = PlayerController.Instance.unlockWallJump; writer.Write(playerUnlockWallJump); playerUnlockDash = PlayerController.Instance.unlockDash; writer.Write(playerUnlockDash); playeUnlockAirJump = PlayerController.Instance.unlockAirJump; writer.Write(playeUnlockAirJump); playerUnlockSideSpell = PlayerController.Instance.unlockSideSpell; writer.Write(playerUnlockSideSpell); //位置 playerPosition = PlayerController.Instance.transform.position; writer.Write(playerPosition.x); writer.Write(playerPosition.y); //場景 lastScene = SceneManager.GetActiveScene().name; writer.Write(lastScene); //地圖TEST writer.Write(sceneName.Count); foreach (string sceneName in sceneName) { writer.Write(sceneName); } } } public void LoadPlayerData() { //string savePath = Application.persistentDataPath + "/save.player.data"; //if (File.Exists(savePath) && new FileInfo(savePath).Length > 0) if(File.Exists(Application.persistentDataPath + "/save.player.data")) { using (BinaryReader reader = new BinaryReader(File.OpenRead(Application.persistentDataPath + "/save.player.data"))) { //血量、魔力 playerHealth = reader.ReadSingle(); playerMana = reader.ReadSingle(); //技能 playerUnlockWallJump = reader.ReadBoolean(); playerUnlockDash = reader.ReadBoolean(); playeUnlockAirJump = reader.ReadBoolean(); playerUnlockSideSpell = reader.ReadBoolean(); //位置 playerPosition.x = reader.ReadSingle(); playerPosition.y = reader.ReadSingle(); //場景 lastScene = reader.ReadString(); Debug.Log(lastScene + "LoadPlayerData by SaveData.cs"); //地圖TEST int sceneCount = reader.ReadInt32(); sceneName = new HashSet<string>(); for (int i = 0; i < sceneCount; i++) { string _sceneName = reader.ReadString(); sceneName.Add(_sceneName); } SceneManager.LoadScene(lastScene); PlayerController.Instance.transform.position = playerPosition; PlayerController.Instance.Health = playerHealth; PlayerController.Instance.Mana = playerMana; PlayerController.Instance.unlockWallJump = playerUnlockWallJump; PlayerController.Instance.unlockDash = playerUnlockDash; PlayerController.Instance.unlockAirJump = playeUnlockAirJump; PlayerController.Instance.unlockSideSpell = playerUnlockSideSpell; } Debug.Log("load player data"); } else { //如果檔案不存在 Debug.Log("File doesnt exist"); PlayerController.Instance.Health = PlayerController.Instance.maxHealth; PlayerController.Instance.Mana = 0.5f; PlayerController.Instance.unlockWallJump = false; PlayerController.Instance.unlockDash = false; PlayerController.Instance.unlockAirJump = false; PlayerController.Instance.unlockSideSpell = false; //地圖TEST sceneName = new HashSet<string>(); } } /* public void SaveSceneData() { using (BinaryWriter writer = new BinaryWriter(File.OpenWrite(Application.persistentDataPath + "/save.scenes.data"))) { writer.Write(sceneName.Count); foreach (string sceneName in sceneName) { writer.Write(sceneName); } } } public void LoadSceneData() { if (File.Exists(Application.persistentDataPath + "/save.scenes.data")) { using (BinaryReader reader = new BinaryReader(File.OpenRead(Application.persistentDataPath + "/save.scenes.data"))) { int sceneCount = reader.ReadInt32(); sceneName = new HashSet<string>(); for (int i = 0; i < sceneCount; i++) { string _sceneName = reader.ReadString(); sceneName.Add(_sceneName); } } } else { sceneName = new HashSet<string>(); } } */ /* public void ResetSavePoint() { savePointSceneName = null; savePointPos = Vector2.zero; } public void ResetPlayerData() { playerHealth = PlayerController.Instance.maxHealth; playerMana = 0; lastScene = null; playerUnlockWallJump = false; playerUnlockDash = false; playeUnlockAirJump = false; playerUnlockSideSpell = false; } public void ResetSceneData() { sceneName.Clear(); } public void DeleteScenesData()//刪除資料 { string path = Application.persistentDataPath + "/save.scenes.data"; if (File.Exists(path)) { File.Delete(path); Debug.Log("Scenes data deleted."); } ResetSceneData(); } public void DeletePlayerData()//刪除資料 { string path = Application.persistentDataPath + "/save.player.data"; if (File.Exists(path)) { File.Delete(path); Debug.Log("Player save data deleted."); } ResetPlayerData(); } public void DeleteSavePointData()//刪除資料 { string path = Application.persistentDataPath + "/save.savePoint.data"; if (File.Exists(path)) { File.Delete(path); Debug.Log("SavePoint save data deleted."); } ResetSavePoint(); } public void DeleteAllSaveData() { DeleteScenesData(); DeleteSavePointData(); DeletePlayerData(); } */ } </code>
August 5, 2024 at 9:55 pm #15504::If you take a look at your code again, your
LoadSceneData()
method code is wrong.public void LoadSceneData() { if (File.Exists(Application.persistentDataPath + "/save.scenes.data")) { using (BinaryReader reader = new BinaryReader(File.OpenRead(Application.persistentDataPath + "/save.scenes.data"))) { int sceneCount = reader.ReadInt32();
sceneName = new HashSet[string]();for (int i = 0; i < sceneCount; i++) { string _sceneName = reader.ReadString(); sceneName.Add(_sceneName); } } } else { sceneName = new HashSet<string>(); } }That line that you moved into
LoadPlayerData()
is a problem because what you are doing is resetting all saved maps every time you want to load them. -
AuthorPosts
- You must be logged in to reply to this topic.
Advertisement below: