Forum begins after the advertisement:

 


[Part 7] Map problem

  • This topic has 70 replies, 4 voices, and was last updated 1 year ago by MI NI.
Viewing 20 posts - 21 through 40 (of 71 total)
  • Author
    Posts
  • #15492
    MI NI
    Level 16
    Former Patron
    Helpful?
    Up
    0
    ::
    #15493
    Joseph Tang
    Level 13
    Moderator
    Helpful?
    Up
    0
    ::

    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?

    #15495
    MI NI
    Level 16
    Former Patron
    Helpful?
    Up
    0
    ::

    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?

    #15496
    Joseph Tang
    Level 13
    Moderator
    Helpful?
    Up
    0
    ::

    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.

    #15497
    MI NI
    Level 16
    Former Patron
    Helpful?
    Up
    0
    ::

    Thanks for your tutorial, I used t:SaveData and double-checked that I did not place SaveData.cs in any game object

    #15500
    Terence
    Level 31
    Keymaster
    Helpful?
    Up
    0
    ::

    MI NI, can you try changing the SaveData object to be a class instead of a struct. See if it fixes the issue.

    #15501
    MI NI
    Level 16
    Former Patron
    Helpful?
    Up
    0
    ::

    After I changed struct to class, an error occurred in the game

    #15502
    Joseph Tang
    Level 13
    Moderator
    Helpful?
    Up
    0
    ::

    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 in Initialize. The issue with that is the fact that your GameManager.cs calls your SaveData.cs Initialize() method in Awake().

    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 your sceneNames data, that you load through LoadSceneData() every time you enter a scene, is empty. Thereby causing your sceneNames 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() in Initialize(), I marked it above, and also look towards calling SaveSceneData() and LoadSceneData() somewhere else more appropriate, like in your SavePlayerData().

    #15503
    MI NI
    Level 16
    Former Patron
    Helpful?
    Up
    0
    ::

    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>
    #15504
    Joseph Tang
    Level 13
    Moderator
    Helpful?
    Up
    0
    ::

    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.

    #15505
    MI NI
    Level 16
    Former Patron
    Helpful?
    Up
    0
    ::

    I don’t know how to mark the text with a green background or a red background in the code, I use //NEW and //Delete instead

    I tried making changes but it didn’t work, I was actually trying to move the SaveSceneData() and LoadSceneData() routines into SavePlayerData() and LoadPlayerData(). But just in case I still tested the modifications you told me, and also I found that my SaveSceneData() was not called and I tried to add it to the interaction of my Bench.cs but also doesn’t work

    <code>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
                }
                //NEW
                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);
    
                //NEW
                /*
                //地圖
                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");
    
                //NEW
                    /*
                    //地圖
                    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;
    
                //NEW
                /*
                //地圖
                sceneName = new HashSet<string>();
                */
            }
        }
    
    
                    //Delete
        public void SaveSceneData()
        {
            using (BinaryWriter writer = new BinaryWriter(File.OpenWrite(Application.persistentDataPath + "/save.scenes.data")))
            {
                Debug.Log("SaveScene bySavedata.cs");
                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>();
            }
        }</code>
    <code>public class SavePoint : MonoBehaviour
    {
        public bool interacted;
        bool inRange = false;
    
        void Update()
        {
            if(Input.GetButtonDown("Interact") && inRange )
            {
                interacted = true;
    
                SaveData.Instance.savePointSceneName = SceneManager.GetActiveScene().name;
                SaveData.Instance.savePointPos = new Vector2(gameObject.transform.position.x, gameObject.transform.position.y);
    
                GameManager.Instance.platformingRespawnPoint = SaveData.Instance.savePointPos;
    
                SaveData.Instance.SavedSavePoint();
                SaveData.Instance.SavePlayerData();
    
                //NEW
                SaveData.Instance.SaveSceneData();
    
                Debug.Log("Save by SavePoint.cs");
            }
        }
    
        private void OnTriggerEnter2D(Collider2D _collision)
        {
            if (_collision.CompareTag("Player")) inRange = true;
        }
    
        private void OnTriggerExit2D(Collider2D _collision)
        {
            if (_collision.CompareTag("Player"))
            {
                //interacted = false;
                inRange = false;
            }
        }
    }</code>
    #15506
    Joseph Tang
    Level 13
    Moderator
    Helpful?
    Up
    0
    ::

    Okay, can you send a video now of how it looks now in the game?

    I’m assuming you travel through the scenes and overall the map works. However upon saving and leaving then reopening the game, your map progress was not properly saved? If so, then after you reopen, try saving at the save point again then open up the map again. I presume you will see your progress has returned.


    If this is the case, the only issue regarding this is that your map only updates when it is opened, and when the bench has been interacted with. But upon starting the game the map starts with no maps progressed except stage 1.

    I would recommend you can try to make a way to update the map on start in some way [which can only be done when the map is active which it isnt by default]. Otherwise, give me some time to make a solution to it if this is the issue.


    If this isn’t the issue, i’ll tell you my new set of thoughts depending on the video.


    also as for how we handle text. right now you use the ' tiddle as your way of marking code. in actuality we use the open and close bracketted arrows for codes: <pre> code </pre>

    One advantage for using ' for code is that you can type out <>. while using <pre> and </pre> will allow the code to automatically be boxed up and have the capability to be highlighted.

    as for marking code yellow: <mark> code </mark> green: <mark class="green"> code </mark> red: <del> code </del>

    #15507
    MI NI
    Level 16
    Former Patron
    Helpful?
    Up
    0
    ::

    I discovered several issues after recording the video. Whether it is restarting Unity or returning to the main menu of the game to continue the game, My map will only have stage_1 after restarting. However, the saved map will be restored after interacting with Bench again.

    In addition, if you restart a new game and interact with Bench, the map saved in the previous game will be restored. This seems to mean that I did not successfully call the map data when continuing the game. And the map data was not deleted when restarting the game.

    I commented out the program I used to integrate the data into SavePlayerData in advance and marked it as //NEW MAP DATA

    <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);
    
                /*
                //NEW MAP DATA
                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");
    
                    /*
                    //NEW MAP DATA
                    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;
    
                /*
                //NEW MAP DATA
                sceneName = new HashSet<string>();
                */
            }
        }
    
    
    
        public void SaveSceneData()
        {
            using (BinaryWriter writer = new BinaryWriter(File.OpenWrite(Application.persistentDataPath + "/save.scenes.data")))
            {
                Debug.Log("SaveScene bySavedata.cs");
                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>();
            }
        }
    
    }
    </code>
    #15508
    Joseph Tang
    Level 13
    Moderator
    Helpful?
    Up
    0
    ::

    As I had already explained above:

    If this is the case, the only issue regarding this is that your map only updates when it is opened, and when the bench has been interacted with. But upon starting the game the map starts with no maps progressed except stage 1.

    I would recommend you can try to make a way to update the map on start in some way [which can only be done when the map is active which it isnt by default]

    I can make you a suggestion to create a duplicate hashset similar to sceneNames in SaveData.cs, as well as a duplicate LoadSceneData() & SaveSceneData() for this new hashset.

    Then instead of using the same SaveSceneData(), inside the duplicate method, change the code to set your duplicate hashset to sceneNames value.

    You should call the duplicate save method inside your Bench script when you interact with it.

    Then in your GameManager.cs, call SaveSceneData() inside SaveScene() instead of calling it from the bench script.

    Then, you can call your duplicate load method inside MapManager.cs OnEnable(), before callling UpdateMap() without the need of checking for the bench interaction. Finally swap out sceneNames in the UpdateMap() method with your duplicate hashset.


    Doing so should help make your map manager check your scene data instead of checking your bench interaction to update your map. Furthermore, you wont be taking the constantly updating sceneNames data but what you actually saved instead.

    Furthermore, should you close the game, all unupdated maps will be saved in sceneNames through the gamemanager calling SaveSceneData() constantly.

    #15511
    MI NI
    Level 16
    Former Patron
    Helpful?
    Up
    0
    ::

    I’m sorry for my stupidity, maybe I’m not sure what you mean due to translation. I tried adding (mark) in (pre)(/pre) but I don’t know if this is how to use it

    I created a new Hashset named mapName and created duplicate LoadSceneData() and SaveSceneData() . I changed it to Load and SaveMapData().

    But I don’t quite understand. Then instead of using the same SaveSceneData(), inside the duplicate method, change the code to set your duplicate hashset to sceneNames value. How to do this

    
     //map stuff
        public HashSet<string> sceneName;
    
         public HashSet[string] mapName; 
    
    .....
    
    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.maps.data"))
            {
                using (BinaryWriter writer = new BinaryWriter(File.Create(Application.persistentDataPath + "/save.maps.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]();
            }
    ;
            if (mapName == null) //檢查此場景是否為空 
            {
                //如果是,建立一個新HashSet
                mapName = new HashSet[string]();
            }
    
    
        }
    
    .....
    
     public void SaveSceneData()
        {
            using (BinaryWriter writer = new BinaryWriter(File.OpenWrite(Application.persistentDataPath + "/save.scenes.data")))
            {
                Debug.Log("SaveScene bySavedata.cs");
                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 SaveMapData()
        {
            using (BinaryWriter writer = new BinaryWriter(File.OpenWrite(Application.persistentDataPath + "/save.maps.data")))
            {
                Debug.Log("Savemaps bySavedata.cs");
                writer.Write(mapName.Count);
                foreach (string mapName in mapName)
                {
                    writer.Write(mapName);
                }
            }
        }
    
        public void LoadMapData()
        {
            if (File.Exists(Application.persistentDataPath + "/save.maps.data"))
            {
                using (BinaryReader reader = new BinaryReader(File.OpenRead(Application.persistentDataPath + "/save.maps.data")))
                {
                    int mapCount = reader.ReadInt32();
                    for (int i = 0; i < mapCount; i++)
                    {
                        string _mapName = reader.ReadString();
                        mapName.Add(_mapName);
                    }
                }
            }
            else
            {
                mapName = new HashSet[string]();
            }
        }
    
    
    #15514
    Joseph Tang
    Level 13
    Moderator
    Helpful?
    Up
    0
    ::

    No, you used the marks correctly, it’s just the post that didn’t load your message correctly.


    Sorry for the unclear instructions. But here’s how you should change your code for each script first:

    SaveData.cs

    First We’ll stop loading the scene data since it will keep resetting the data incorrectly. We’ll instead call it somewhere else.

    Next we’ll have to make our mapName by taking the same value as sceneName.

    In this case, mapName will be called by our MapManager.cs to update the map. Whereas sceneName is only used to retain the information of scenes that we’ve been through.

    1. Remove calling for LoadSceneData() in Initialize()
    2. In SaveMapData(), set mapName to sceneName
        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.maps.data"))
            {
                using (BinaryWriter writer = new BinaryWriter(File.Create(Application.persistentDataPath + "/save.maps.data")))
                {
                    writer.Write(0); // Write an empty scene data structure
                }
                LoadSceneData();
            }
            ...
        }
    
        public void SaveMapData()
        {
            using (BinaryWriter writer = new BinaryWriter(File.OpenWrite(Application.persistentDataPath + "/save.maps.data")))
            {
                Debug.Log("Savemaps bySavedata.cs");
    
                mapName = sceneName;
    
                writer.Write(mapName.Count);
                foreach (string mapName in mapName)
                {
                    writer.Write(mapName);
                }
            }
        }

    MapManager.cs

    Make sure that mapName is used in UpdateMap().

    1. In UpdateMap() change the load of sceneName to mapName instead
        public void UpdateMap()
        {
            var savedScenes = SaveData.Instance.sceneName;
    
            var savedScenes = SaveData.Instance.mapName;
    
            for(int i = 0; i < maps.Length; i++)
            {
                if(savedScenes.Contains("Cave_" + (i + 1))) //this is i + 1 as arrays start from 0
                {
                    maps[i].SetActive(true);
                }
                else
                {
                    maps[i].SetActive(false);
                }
            }
        }

    GameManager.cs

    We also have to make sure to save all our visited scene data somehow, which we’ll do so by calling SaveSceneData() through the same method we used to save the scenes, SaveScene().

    Then also make sure that we’ve loaded the saved information whenever we open the game by calling our load methods in the Awake() function.

    1. Call LoadMapData() and LoadSceneData() in Awake()
    2. In SaveScene(), call SaveSceneData()
        private void Awake()
        {
            ....
    
            SaveScene();
    
            DontDestroyOnLoad(gameObject);
    
            SaveData.Instance.LoadSceneData();
    
            SaveData.Instance.LoadMapData();
        }
    
        public void SaveScene()
        {
            string currentSceneName = SceneManager.GetActiveScene().name;
            SaveData.Instance.sceneNames.Add(currentSceneName);
            SaveData.Instance.SaveSceneData();
        }

    SavePoint.cs

    Finally, we want to update our mapName by calling SaveMapData(), which we’ll do so through the Bench/SavePoint since that’s how they will be updated.

    1. Call SaveMapData() in Update()
        void Update()
        {
            if (Input.GetButtonDown("Interact") && inRange)
            {
                interacted = true;
    
                SaveData.Instance.benchSceneName = SceneManager.GetActiveScene().name;
                SaveData.Instance.benchPos = new Vector2(gameObject.transform.position.x, gameObject.transform.position.y);
                SaveData.Instance.SaveBench();
                SaveData.Instance.SavePlayerData();
                SaveData.Instance.SaveMapData();
            }
        }

    With that, this should be all you need to save and load your map data.

    #15515
    MI NI
    Level 16
    Former Patron
    Helpful?
    Up
    0
    ::

    The post doesn’t seem to be loading my messages correctly again, I’m not sure if I should remove those tags so you can view them

    After I made the above modifications, it was still the same as before, but I tried to find the error point. I found that the <per>mapsName</per> was actually stored after entering the game, so I couldn’t find the error. I finally printed the error in <per>UpdateMap()</per> <per>maps[i].SetActive(true&false);</per>, I found that when entering the game and pressing to open the map, <per>UpdateMap()</per> will not be loaded. It will only be loaded after interacting with the storage point and pressing to open the map. This is weird, what do you think?

    <per>void UpdateMap() { //var savedScenes = SaveData.Instance.sceneName; var savedScenes = SaveData.Instance.mapName;

        for (int i = 0; i < maps.Length ; i++)
        {
            if(savedScenes.Contains("Stage_" + (i + 1))) //此處為地圖名稱
            {
                maps[i].SetActive(true);
                Debug.Log(savedScenes.Contains("Stage_" + (i + 1)));
    
            }
            else
            {
                maps[i].SetActive(false);
                Debug.Log(savedScenes.Contains("Stage_" + (i + 1)));
            }
        }
    }</per>
    #15516
    MI NI
    Level 16
    Former Patron
    Helpful?
    Up
    0
    ::

    I think I found the problem. In MapManager, OnEnable() will only execute UpdateMap() after interacting with Bench.cs; I’m not sure if I should keep this code and would like to know what you think. In addition, when I create a new game, the maps data cannot be deleted correctly, but I don’t know what went wrong.

    Update Post, I found that moving UpdateMap() outside will cause it to go to any stage, and there will be no need to find the save point to update the map, so my idea is to declare UpdateMap() as public, and in Execute UpdateMap() once in PlayerController’s Awake(). I would like to know if there is a better way to try.

    <per>private void OnEnable() { savePoint = FindObjectOfType<SavePoint>(); <mark class=”green”> UpdateMap(); / if (savePoint != null) { if(savePoint.interacted) { UpdateMap(); } } / }</per>

    <per>public class MenuSaveData : MonoBehaviour { public void ResetSaveData() { string path = Application.persistentDataPath;

        // Delete all save files if they exist
        string[] saveFiles = {
        path + "/save.savePoint.data",
        path + "/save.player.data",
        path + "/save.scenes.data",
         path + "/save.maps.data" 
        //path + "/save.shade.data"
    };
    
        foreach (string saveFile in saveFiles)
        {
            try
            {
                if (File.Exists(saveFile))
                {
                    File.Delete(saveFile);
                    Debug.Log(saveFile + " deleted.");
                }
            }
            catch (System.Exception ex)
            {
                Debug.LogError("Failed to delete " + saveFile + ": " + ex.Message);
            }
        }
    
        // Ensure SaveData is initialized
        SaveData.Instance.Initialize();
    
        //SaveData.Instance.DeleteAllSaveData();
    
        // Forcefully set the tutorial scene
        SaveData.Instance.lastScene = new string("Stage_1");
    
        Debug.Log("All save data has been reset.");
    }</per>
    #15533
    Joseph Tang
    Level 13
    Moderator
    Helpful?
    Up
    0
    ::

    When you are using the code blocks, you can still use ' instead of <pre>

    I do not see your issue with the mapName, in the sense that i don’t believe you’ve described what is going on with it that is a problem. Could you show a video with how the mapName fails to be deleted or load correctly on start?

    Regarding your proposed fix. The reason for UpdateMap() to be called in OnEnable() only after interacting with the save point is because we are following Hollow Knight in the tutorial.

    To be clear, the mechanic is supposed to work the way it does as you experienced. Which is that the map will only update once you save the game at a save point.

    However, you can change it to fit the needs of your game. Which also means that your change is okay.

    #15535
    MI NI
    Level 16
    Former Patron
    Helpful?
    Up
    0
    ::

    This is my video. In the video I try to print out the saved content while executing LoadMapData(). When I re-entered Stage 2, Stage 1 and Stage 2 were indeed printed out, but I still needed to interact with Bench again to restore the saved map data.It also demonstrated that I could not delete the data correctly when creating a new game.

Viewing 20 posts - 21 through 40 (of 71 total)
  • You must be logged in to reply to this topic.

Go to Login Page →


Advertisement below: