Forum begins after the advertisement:
[Part 5] Map didn’t update on scene and scene fading make the game freeze
Home › Forums › Video Game Tutorial Series › Creating a Metroidvania in Unity › [Part 5] Map didn’t update on scene and scene fading make the game freeze
- This topic has 13 replies, 2 voices, and was last updated 1 week, 6 days ago by pepecry.
-
AuthorPosts
-
November 3, 2024 at 7:00 pm #16236::
So i’m on the map making process and I was trying using Aka method (the method he share in the pin post of the forum) to making map. It look good but I think there is some thing maybe need to be adjust, If you know how to do that pls tell me. I’m not testing it out yet but there is some problem with the map update. The map it show all the map,not the only scene of the map like the video. for the code, here is the map handler script
using System.Collections; using System.Collections.Generic; using UnityEngine; public class MapManager : MonoBehaviour { public static MapManager Instance { get; private set; } [SerializeField] GameObject[] maps; Alter alter; private void Awake() { if (Instance == null) { Instance = this; } else if (Instance != this) { Destroy(gameObject); } } // Start is called before the first frame update void Start() { UpdateMap(); } // Update is called once per frame public void UpdateMapState() { UpdateMap(); } public void UpdateMap() { if (SaveData.Instance.sAlterActivated) { var savedScenes = SaveData.Instance.sceneNames; for (int i = 0; i < maps.Length; i++) { bool isActive = savedScenes.Contains("Map_" + (i + 1)); maps[i].SetActive(isActive); } Debug.Log("Maps updated based on saved scenes."); } } private void OnEnable() { alter = FindObjectOfType<Alter>(); if(alter != null) { if (alter.Interacted) { UpdateMapState(); } } } }
my alter script
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.SceneManagement; public class Alter : MonoBehaviour { [HideInInspector] public Move player; private bool isInMachine = false; public bool Interacted; [HideInInspector] public bool isSaving = false; // Start is called before the first frame update void Start() { player = Move.Instance; } // Update is called once per frame void Update() { SaveActive(); } private void OnTriggerEnter2D(Collider2D _other) { if (_other.CompareTag("Player")) { isInMachine = true; } } private void OnTriggerExit2D(Collider2D _other) { if (_other.CompareTag("Player")) { isInMachine = false; isSaving = false; } } private void OnTriggerStay2D(Collider2D _collision) { if (_collision.CompareTag("Player") && Input.GetButtonDown("Interact")) { Interacted = true; } } private void SaveActive() { if (Interacted = true && isInMachine) { isSaving = true; SaveData.Instance.SaveAlterActivated(); MapManager.Instance.UpdateMapState(); string currentSceneName = SceneManager.GetActiveScene().name; SaveData.Instance.sceneNames.Add(currentSceneName); SaveData.Instance.SaveMapData(); Debug.Log("Scenes saved: " + string.Join(", ", SaveData.Instance.sceneNames)); // StartCoroutine(Saving()); isSaving = false; } } }
and gamemanager script
using System.Collections; using System.Collections.Generic; using UnityEngine; using Cinemachine; using UnityEngine.SceneManagement; using UnityEngine.EventSystems; public class GameManager : MonoBehaviour { // Start is called before the first frame update [SerializeField] Alter saveAlter; public string transitionFromScene; public static GameManager Instance { get; private set; } public Vector2 respawnpoint; [SerializeField] Alter alter; public Vector2 platformRespawnpoint; private void Awake() { SaveData.Instance.Initialize(); if (Instance != null && Instance != this) { Destroy(gameObject); } else { Instance = this; } SaveData.Instance.LoadMapData(); EnsureEventSystem(); DontDestroyOnLoad(gameObject); alter = FindObjectOfType<Alter>(); } public void respawnPlayer() { if(alter != null) { if (alter.Interacted) { respawnpoint = alter.transform.position; } else { respawnpoint = platformRespawnpoint; } } else { respawnpoint = platformRespawnpoint; } Move.Instance.transform.position = respawnpoint; StartCoroutine(UIManager.Instance.DeactiveDeathScreen()); Move.Instance.Respawn(); } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { Debug.Log($"OnSceneLoaded: {scene.name}"); SaveScene(); } private void OnEnable() { SceneManager.sceneLoaded += OnSceneLoaded; Debug.Log("GameManager: Subscribed to sceneLoaded."); } private void OnDisable() { SceneManager.sceneLoaded -= OnSceneLoaded; Debug.Log("GameManager: Unsubscribed from sceneLoaded."); } public void SaveScene() { string currentSceneName = SceneManager.GetActiveScene().name; SaveData.Instance.sceneNames.Add(currentSceneName); SaveData.Instance.SaveMapData(); Debug.Log($"Scene saved: {currentSceneName}"); } private void EnsureEventSystem() { if (FindObjectOfType<EventSystem>() == null) { GameObject eventSystemGO = new GameObject("EventSystem"); eventSystemGO.AddComponent<EventSystem>(); eventSystemGO.AddComponent<StandaloneInputModule>(); } } }
the ispector of the map handler
and I already tried to call updatemapstate and updatemap but neither it work.
Another problem that if I turn of the scene fading. The game work itself but in the console said that it null reference. But If I turn it on, the game freeze with a black scene and the mana img, sometime it doesn’t show up anything. Just a black scene like in the picture below
And yet it said I have a null reference in the scene transition. Eventhought I have assign everything in it
Did you guys know how to fix it and/or just don’t apply the Aka method for the code, pls let me know. Tks youNovember 4, 2024 at 4:25 pm #16240::pepe, can you post your
SceneTransition
script? Let’s fix the NullReferenceException first.Check out this 1 minute video on fixing NullReferenceExceptions as well:
November 4, 2024 at 6:49 pm #16241::using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.SceneManagement; public class SceneTransition : MonoBehaviour { // Start is called before the first frame update [SerializeField] private string transitionTo; [SerializeField] private Transform startPoint; [SerializeField] private Vector2 directionExit; [SerializeField] private float exitTime; private void Start() { if (transitionTo == GameManager.Instance.transitionFromScene) { Move.Instance.transform.position = startPoint.position; StartCoroutine(Move.Instance.WalktonewScene(directionExit,exitTime)); } StartCoroutine(UIManager.Instance.sceneFading.Fade(SceneFading.fadeDirection.Out)); } private void OnTriggerEnter2D(Collider2D _other) { if (_other.CompareTag("Player")) { GameManager.Instance.transitionFromScene = SceneManager.GetActiveScene().name; Move.Instance.playerStateList.incutscene = true; StartCoroutine(UIManager.Instance.sceneFading.FadeAndLoadScene(SceneFading.fadeDirection.In,transitionTo)); } } }
This is the scene transition script. Does anything goes wrong? After Watching the video you send, I’m think that none of them causing the problem. If yes, then it must be the first one or the second one. Could it be of mine PlayerController script(Move is the name of the playercontroller script)? Because in the transition script, there is nothing more I can assign
November 5, 2024 at 12:46 am #16253::So we will need to figure all 2 null ref because I just findout another problem. Before it being null ref like this. I has test it and work fine. But when I change how the method work. The alter(bench) got null ref like this
And here the scriptusing System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.SceneManagement; public class Alter : MonoBehaviour { [HideInInspector] public Move player; private bool isInMachine = false; public bool Interacted; [HideInInspector] public bool isSaving = false; // Start is called before the first frame update void Start() { player = Move.Instance; } // Update is called once per frame void Update() { SaveActive(); } private void OnTriggerEnter2D(Collider2D _other) { if (_other.CompareTag("Player")) { isInMachine = true; } } private void OnTriggerExit2D(Collider2D _other) { if (_other.CompareTag("Player")) { isInMachine = false; isSaving = false; } } private void OnTriggerStay2D(Collider2D _collision) { if (_collision.CompareTag("Player") && Input.GetButtonDown("Interact")) { Interacted = true; } } private void SaveActive() { if (Interacted = true && isInMachine) { isSaving = true; SaveData.Instance.SaveAlterActivated(); MapManager.Instance.UpdateMapState(); string currentSceneName = SceneManager.GetActiveScene().name; SaveData.Instance.sceneNames.Add(currentSceneName); SaveData.Instance.SaveMapData(); Debug.Log("Scenes saved: " + string.Join(", ", SaveData.Instance.sceneNames)); // StartCoroutine(Saving()); isSaving = false; } } }
So with your video, I has tried to call the getcomponent by
player = GetComponent<Move>();
But it not work though. I know that we should work for one by one problem as the time but these has the same error. Should we fix it together?November 5, 2024 at 7:54 pm #16254::Your NullReferenceException in the SceneTransition seems to be caused by this line:
StartCoroutine(UIManager.Instance.sceneFading.Fade(SceneFading.fadeDirection.Out));
This happens because your
Start()
function onSceneTransition
starts before theUIManager
one, which causes either theInstance
orsceneFading
variables to not be registered. You can try changing theStart()
function inUIManager
toAwake()
to see if it fixes the issue.For the
Alter
script, can you confirm if this line is the one causing the issue?string currentSceneName = SceneManager.GetActiveScene().name;
November 5, 2024 at 10:08 pm #16256::Sorry for replying late but I has figure out the reason. My map handler for some reason doesn’t had the MapHandler script Anymore eventhought I had assign it to the map handler before and test the map perfectly (althought it show up full map thought) before. That is why it cause up these errors. I can start the game perfectly now. Now the problem turn to the alter but not the null ref anymore. It about saving. I use these code
private void OnTriggerEnter2D(Collider2D _other) { if (_other.CompareTag("Player") && Input.GetButtonDown("Interact")) { isInMachine = true; Interacted = true; SaveData.Instance.alterSceneName = SceneManager.GetActiveScene().name; SaveData.Instance.alterPos = new Vector2(gameObject.transform.position.x, gameObject.transform.position.y); SaveData.Instance.SaveMapData(); } } private void OnTriggerExit2D(Collider2D _other) { if (_other.CompareTag("Player")) { isInMachine = false; isSaving = false; } }
to get saved but when I enter the alter and press F. It doesn’t save. If the save is done correctly like these code
private void SaveActive() { if (Interacted && isInMachine) { isSaving = true; SaveData.Instance.SaveAlterActivated(); MapManager.Instance.UpdateMapState(); string currentSceneName = SceneManager.GetActiveScene().name; SaveData.Instance.sceneNames.Add(currentSceneName); SaveData.Instance.SaveMapData(); Debug.Log("Scenes saved: " + string.Join(", ", SaveData.Instance.sceneNames)); // StartCoroutine(Saving()); isSaving = false; }
It should have the log scene save. But there nothing appear in my console and the map didn’t update as you can see in the record below
If you need me to provide anything, pls let me know. I will do it ASAP. Tks for your help
November 5, 2024 at 10:20 pm #16258::Did you see my reply? I just edit something in it and it disapear. But in conclusion, I fix the ref null by finding that the maphandler doesn’t have it script. And now the problem is come up by the alter. It doesn’t save like the video below
Alter save record
The map also don’t update so that I’m kinda sure that the save doesn’t work. If it work it must like in this recordprivate void SaveActive() { if (Interacted && isInMachine) { isSaving = true; SaveData.Instance.SaveAlterActivated(); MapManager.Instance.UpdateMapState(); string currentSceneName = SceneManager.GetActiveScene().name; SaveData.Instance.sceneNames.Add(currentSceneName); SaveData.Instance.SaveMapData(); Debug.Log("Scenes saved: " + string.Join(", ", SaveData.Instance.sceneNames)); // StartCoroutine(Saving()); isSaving = false; }
And i use the code to make save
private void OnTriggerEnter2D(Collider2D _other) { if (_other.CompareTag("Player") && Input.GetButtonDown("Interact")) { isInMachine = true; Interacted = true; SaveData.Instance.alterSceneName = SceneManager.GetActiveScene().name; SaveData.Instance.alterPos = new Vector2(gameObject.transform.position.x, gameObject.transform.position.y); SaveData.Instance.SaveMapData(); } } private void OnTriggerExit2D(Collider2D _other) { if (_other.CompareTag("Player")) { isInMachine = false; isSaving = false; } }
Tks you for your help
November 5, 2024 at 10:32 pm #16259::You need to figure out why the maps in your
MapManager
go missing when the game is playing. At a glance, one possibility is that the prefabs you assign are from the Scene, instead of prefabs from your project files.November 5, 2024 at 10:51 pm #16260::So how should I do? open the canvas in the prefab folder and add it? Because as I see in the video, they doing by adding it in the canvas in the scene and then drag and drop
You could see it in the point of the link i send. If i do something wrong, pls note it for meNovember 6, 2024 at 8:47 am #16261::Try reassigning your map GameObjects with the prefabs in your project files and see if the issue of them turning Missing still happens.
November 6, 2024 at 4:44 pm #16265::Here is mine prefab folder
I could access to the canvas but i can’t access to the children of it. As you could see in the inspector down here
So I don’t know what should I assign it to. And I can’t make the children of a prefab to be a prefab.
Or should change my scene name that have Map_ to it name and assign it?
But at this point, I’m kinda think of the code fault than the canvas. I have a spawnpoint in here as you could see
But in the recording below. Even if i touch the respawn point, my character still do not spawn at that point but somewhere up in the middle of the room
Repawnpoint test record
My character even got drop down and go through the floor. So could we consider it the code problem? Or still the problem is the canvas prefab assign problem? And yes. I had tried many ways to fix that. From access to prefab scene, in hierachy but doesn’t seem anything work.November 8, 2024 at 7:21 am #16270::I go back for the video code and adjust the code like in the video. When try to openmap, the game has this error
The problem is before I turn of the Unity, I can open up the map normaly. but when i turn it on again, this error happend. About the code. I made it as same as the tutorial video does. You could check it hereusing System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.SceneManagement; public class Alter : MonoBehaviour { public bool Interacted; // Start is called before the first frame update void Start() { } // Update is called once per frame void Update() { } private void OnTriggerStay2D(Collider2D _other) { if (_other.CompareTag("Player") && Input.GetButtonDown("Interact")) { Interacted = true; SaveData.Instance.altersceneName = SceneManager.GetActiveScene().name; SaveData.Instance.alterPos = new Vector2(gameObject.transform.position.x,gameObject.transform.position.y); SaveData.Instance.saveAlter(); SaveData.Instance.savePlayerData(); } } private void OnTriggerExit2D(Collider2D _collision) { if (_collision.CompareTag("Player") ) { Interacted = false; } } }
That is the code for alter(bench)
Here is the code for SaveDatausing System.Collections; using System.Collections.Generic; using UnityEngine; using System.IO; using UnityEngine.SceneManagement; [System.Serializable] public struct SaveData { public static SaveData Instance; public HashSet<string> sceneNames; public string altersceneName; public Vector2 alterPos; public int playerHealth; public float playerMana; public Vector2 playerPosition; public string lastScene; public void Initialize() { if (!File.Exists(Application.persistentDataPath + "/save.alter.data")) { BinaryWriter writer = new BinaryWriter(File.Create(Application.persistentDataPath + "/save.alter.data")); } if (!File.Exists(Application.persistentDataPath + "/save.player.data")) { BinaryWriter writer = new BinaryWriter(File.Create(Application.persistentDataPath + "/save.player.data")); } if (sceneNames == null) { sceneNames = new HashSet<string>(); } } public void saveAlter() { using (BinaryWriter writer = new BinaryWriter(File.OpenWrite(Application.persistentDataPath + "/save.alter.data"))) { writer.Write(altersceneName); writer.Write(alterPos.x); writer.Write(alterPos.y); } } public void loadAlter() { if (File.Exists(Application.persistentDataPath + "/save.alter.data")) { using(BinaryReader reader = new BinaryReader(File.OpenRead(Application.persistentDataPath + "/save.alter.data"))) { altersceneName = reader.ReadString(); alterPos.x = reader.ReadSingle(); alterPos.y = reader.ReadSingle(); } } } public void savePlayerData() { using (BinaryWriter writer = new BinaryWriter(File.OpenWrite(Application.persistentDataPath + "/save.player.data"))) { playerHealth = Move.Instance.Health; writer.Write(playerHealth); playerMana = Move.Instance.Mana; writer.Write(playerMana); playerPosition = Move.Instance.transform.position; writer.Write(playerPosition.x); writer.Write(playerPosition.y); lastScene = SceneManager.GetActiveScene().name; writer.Write(lastScene); } } public void loadPlayerData() { if(File.Exists(Application.persistentDataPath + "/save.player.data")) { using(BinaryReader reader = new BinaryReader(File.OpenRead(Application.persistentDataPath + "/save.player.data"))) { playerHealth = reader.ReadInt32(); playerMana = reader.ReadSingle(); playerPosition.x = reader.ReadSingle(); playerPosition.y = reader.ReadSingle(); lastScene = reader.ReadString(); SceneManager.LoadScene(lastScene); Move.Instance.transform.position = playerPosition; Move.Instance.Health = playerHealth; Move.Instance.Mana = playerMana; } } else { Debug.Log("File doesn't exist"); Move.Instance.Health = Move.Instance.MaxHealth; Move.Instance.Mana = 0.5f; } } }
The gamemanager
using System.Collections; using System.Collections.Generic; using UnityEngine; using Cinemachine; using UnityEngine.SceneManagement; using UnityEngine.EventSystems; public class GameManager : MonoBehaviour { // Start is called before the first frame update public string transitionFromScene; public static GameManager Instance { get; private set; } public Vector2 respawnpoint; [SerializeField] Alter alter; public Vector2 platformRespawnpoint; private void Awake() { if (Instance != null && Instance != this) { Destroy(gameObject); } else { Instance = this; } DontDestroyOnLoad(gameObject); alter = FindObjectOfType<Alter>(); } private void Update() { if(Input.GetKeyDown(KeyCode.P)) { SaveData.Instance.savePlayerData(); } } public void respawnPlayer() { SaveData.Instance.loadAlter(); if(SaveData.Instance.altersceneName != null) { SceneManager.LoadScene(SaveData.Instance.altersceneName); } if(SaveData.Instance.alterPos != null) { respawnpoint = SaveData.Instance.alterPos; } else { respawnpoint = platformRespawnpoint; } Move.Instance.transform.position = respawnpoint; StartCoroutine(UIManager.Instance.DeactiveDeathScreen()); Move.Instance.Respawn(); } }
and the MapManager
using System.Collections; using System.Collections.Generic; using UnityEngine; using Cinemachine; using UnityEngine.SceneManagement; using UnityEngine.EventSystems; public class GameManager : MonoBehaviour { // Start is called before the first frame update public string transitionFromScene; public static GameManager Instance { get; private set; } public Vector2 respawnpoint; [SerializeField] Alter alter; public Vector2 platformRespawnpoint; private void Awake() { if (Instance != null && Instance != this) { Destroy(gameObject); } else { Instance = this; } DontDestroyOnLoad(gameObject); alter = FindObjectOfType<Alter>(); } private void Update() { if(Input.GetKeyDown(KeyCode.P)) { SaveData.Instance.savePlayerData(); } } public void respawnPlayer() { SaveData.Instance.loadAlter(); if(SaveData.Instance.altersceneName != null) { SceneManager.LoadScene(SaveData.Instance.altersceneName); } if(SaveData.Instance.alterPos != null) { respawnpoint = SaveData.Instance.alterPos; } else { respawnpoint = platformRespawnpoint; } Move.Instance.transform.position = respawnpoint; StartCoroutine(UIManager.Instance.DeactiveDeathScreen()); Move.Instance.Respawn(); } }
To make sure, here is what I assign in case you need
And the save could said it work. But for some reason, after get respawn. My player get freeze and if i try to move. My player is dropdown under the ground. Same as this record but now i’m appear at the alter
dropdown error
My fault. I set the wrong enable of the boxcollider when respawn.
Please help me fix this. thank you so muchNovember 8, 2024 at 11:09 pm #16278::Updating. For some reason, after closing Unity and open after some hour, the game now looking fine, the map is open (but still show all the map without needing to interacted with the alter). The save work. After i start the game, my character shhow up at the alter. not the default position. Now i’m making the wall jump. and it look good. But for some reason. I dont need to interact with the unlock wall jump purple and i still can make wall jump. Even if i set the variable of the unlockwalljump to false. Here you can see the code and the record
private bool Walled() { return Physics2D.OverlapCircle(wallCheck.position, 0.2f, wallLayer); } void WallSlide() { if (Walled() && !isonGround() && xAxis != 0) { iswallSliding = true; rbd2.velocity = new Vector2(rbd2.velocity.x, Mathf.Clamp(rbd2.velocity.y, -wallSlidingSpeed, float.MaxValue)); } else { iswallSliding = false; } } void WallJump() { if (iswallSliding) { iswallJumping = false; wallJumpDirection = !playerStateList.lookingRight ? 1:-1; CancelInvoke(nameof(StopWallJumping)); } if (Input.GetButtonDown("Jump") && iswallSliding) { iswallJumping = true; rbd2.velocity = new Vector2(wallJumpDirection * wallJumpPow.x, wallJumpPow.y); dashed = false; dbJumpCounter = 0; playerStateList.lookingRight = !playerStateList.lookingRight; transform.eulerAngles = new Vector2(transform.eulerAngles.x, 180); Invoke(nameof(StopWallJumping), wallJumpingDuration); } } void StopWallJumping() { iswallJumping = false; transform.eulerAngles = new Vector2(transform.eulerAngles.x, 0); }
public bool unlockWalljump = false; private void Update() { if (playerStateList.incutscene) return; if(playerStateList.alive) { getInput(); OpenMap(); } UpdateJump(); RestoreTimeScale(); if (playerStateList.dashing) return; FlashWhenInvi(); if (playerStateList.alive){ if (!iswallJumping) { Moving(); Flip(); Jump(); } }; Heal(); CastSpell(); if (playerStateList.healing) return; if (unlockWalljump) { WallSlide(); WallJump(); } WallSlide(); WallJump(); StartDash(); Attack(); }
and the recording
walljump record
Do you know what causing this? If you figure out please talk to me. Thank you -
AuthorPosts
- You must be logged in to reply to this topic.
Advertisement below: