Forum begins after the advertisement:


[Part 7] Map problem

Viewing 15 posts - 31 through 45 (of 71 total)
  • Author
    Posts
  • #15505
    MI NI
    Bronze Supporter (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

    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>();
            }
        }
    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;
            }
        }
    }
    #15506
    Joseph Tang
    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
    Bronze Supporter (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

    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>();
            }
        }
    
    }
    
    #15508
    Joseph Tang
    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
    Bronze Supporter (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 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
    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
    Bronze Supporter (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);
    <mark class=”green”>Debug.Log(savedScenes.Contains(“Stage_” + (i + 1)));

    }
    else
    {
    maps[i].SetActive(false);
    <mark class=”green”>Debug.Log(savedScenes.Contains(“Stage_” + (i + 1)));
    }
    }
    }</per>

    #15516
    MI NI
    Bronze Supporter (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”,
    <mark class=”green”> 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
    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
    Bronze Supporter (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.

    #15538
    Joseph Tang
    Moderator
    Helpful?
    Up
    0
    ::

    First. Change your MapManager.cs code to this:

        private void OnEnable()
        {
            SaveData.Instance.LoadMapData();
    
            UpdateMap();
        }

    This should make your maps load properly on start of the game and when you activate a save point.


    next

    Can you send your SaveData.cs code again? I suspect you forgot to delete some items off from the script that is retaining mapName information.

    I’ve tested out the method and overall it is able to save and delete just fine otherwise.

    #15539
    MI NI
    Bronze Supporter (Patron)
    Helpful?
    Up
    0
    ::

    Okay, sorry to trouble you.

    Regarding the first question, I think my initial idea was wrong, which caused you to misunderstand my idea. Regarding this point, I am very concerned about the construction. I think I want to be like Hollow Knight, and only update when interacting with Bench. Map, if according to the method you provided, the map will be updated every time “Map” is pressed, which may not be what I want. But this puts me in a situation where if I restart the game, I cannot update the map to the current progress before interacting with Bench.

    SaveData.cs

    
    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;
    
        public HashSet<string> mapName;
    
        //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
                }
            }
    
            //檢查場景文件是否存在,否則將建立一個新文件
            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
                }
            }
    
            //檢查重生點文件是否存在,否則將建立一個新文件
            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 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);
            }
        }
    
        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");
    
                    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;
    
            }
        }
        
    
        
        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");
    
                mapName = sceneName;
    
                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);
    
                        Debug.Log(_mapName);
                    }
                }
            }
            else
            {
                mapName = new HashSet<string>();
            }
        }
    
    }
    
    #15540
    Joseph Tang
    Moderator
    Helpful?
    Up
    0
    ::

    Actually, i believe it’s the opposite. I am actually making it such that your map only updates after interacting with Bench.

    The reason as to how my method above works is through these steps:

    1. The MapManager calls to UpdateMap().
    2. UpdateMap() will only work when mapName in SaveData.cs has any value.
    3. mapName will only ever be updated after SaveMapData() is called through the Bench/SavePoint.cs

    Thus, ONLY whenever you interact with a bench, you update mapName which thereby updates the maps itself. And with the update method being outside of checking for bench interaction, it means that if you continue a game after exiting, it will still update to the last time you saved progress.

    So long as SaveMapData() is not called anywhere else but the bench before.


    Apart from that, you should change your Initialize() method as I believe that’s part of the reason for the issues you may face with deleting the files. Or it’s worth a shot in any case:

            //檢查場景文件是否存在,否則將建立一個新文件
            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
                }
            }
    
            //檢查場景文件是否存在,否則將建立一個新文件
            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
                }
            }
    
            if (!File.Exists(Application.persistentDataPath + "/save.scenes.data"))
            {
                BinaryWriter writer = new BinaryWriter(File.Create(Application.persistentDataPath + "/save.scenes.data"));
            }
    
            if (!File.Exists(Application.persistentDataPath + "/save.maps.data"))
            {
                BinaryWriter writer = new BinaryWriter(File.Create(Application.persistentDataPath + "/save.maps.data"));
            }
    #15541
    MI NI
    Bronze Supporter (Patron)
    Helpful?
    Up
    0
    ::

    I think I may have encountered too many problems. For the problems that still exist after I made the above changes, I recorded a video to demonstrate the problems I encountered.
    1. After I interact with any Bench, I can directly update the map as long as I enter the map without interacting with the Bench of the map.
    2. After creating a new game, it will be normal to open the map at the beginning, but after interacting with Bench, the last data will be restored.
    3. After I created a new game, I could not call the pause menu again. Although I could not see my keyboard, at the end of the video, I tried to press the ECS key, but it would not respond.

    MapManager.cs

    private void OnEnable()
        {
            savePoint = FindObjectOfType<SavePoint>();
    
            SaveData.Instance.LoadMapData();
    
            UpdateMap();
        }

    #15546
    Joseph Tang
    Moderator
    Helpful?
    Up
    0
    ::

    Okay, I’m going to need you to send me the following scripts:

    MapManager.cs

    SaveData.cs

    GameManager.cs

    SavePoint.cs

    Afterwards, i’ll take a look at your code and get back to you on what went wrong.

Viewing 15 posts - 31 through 45 (of 71 total)
  • You must be logged in to reply to this topic.

Go to Login Page →


Advertisement below: