Forum begins after the advertisement:
[Part 7] Player does not respawn at the correct respawn point
Home › Forums › Video Game Tutorial Series › Creating a Metroidvania in Unity › [Part 7] Player does not respawn at the correct respawn point
- This topic has 5 replies, 2 voices, and was last updated 7 months ago by Joseph Tang.
-
AuthorPosts
-
April 17, 2024 at 5:23 pm #13917::
Hi everyone,
When i try to save the “bench” coordinates and die to see if i respawn back at the correct point, it load for a second at the correct position, but then i get teleported back at starting point and an error appears
NullReferenceException: Object reference not set to an instance of an object UIManager+<DeactivateDeathScreen>d__8.MoveNext () (at Assets/Scripts/UIManager.cs:45) UnityEngine.SetupCoroutine.InvokeMoveNext (System.Collections.IEnumerator enumerator, System.IntPtr returnValueAddress)
Here is the code:
Bench code:
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.SceneManagement; public class SavePoint : MonoBehaviour { [SerializeField]public bool interacted; private void OnTriggerStay2D(Collider2D collision) { if(collision.CompareTag("Player") && Input.GetButtonDown("Interact")) { interacted = true; SaveData.Instance.stoneSceneName = SceneManager.GetActiveScene().name; SaveData.Instance.stonePos = new Vector2(gameObject.transform.position.x, gameObject.transform.position.y); SaveData.Instance.SaveStone(); } } }
Save 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; //stone data public string stoneSceneName; public Vector2 stonePos; //player data public int playerHealth; public Vector2 playerPos; public string lastScene; public void Initialize() { if(!File.Exists(Application.persistentDataPath + "/save.stone.data")) { BinaryWriter writer = new BinaryWriter(File.Create(Application.persistentDataPath + "/save.stone.data")); } } public void SaveStone() { using(BinaryWriter writer = new BinaryWriter(File.OpenWrite(Application.persistentDataPath + "/save.stone.data"))) { writer.Write(stoneSceneName); writer.Write(stonePos.x); writer.Write(stonePos.y); } } public void LoadStone() { string savePath = Application.persistentDataPath + "/save.stone.data"; if (File.Exists(savePath) && new FileInfo(savePath).Length > 0) { using(BinaryReader reader = new BinaryReader(File.OpenRead(Application.persistentDataPath + "/save.stone.data"))) { stoneSceneName = reader.ReadString(); stonePos.x = reader.ReadSingle(); stonePos.y = reader.ReadSingle(); } } } }
Game manager code:
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.SceneManagement; public class GameManager : MonoBehaviour { public string transitionedFromScene; public static GameManager Instance { get; private set; } public Vector2 respawnPoint; [SerializeField] SavePoint stone; private void Awake() { SaveData.Instance.Initialize(); if(Instance != null && Instance != this) { Destroy(gameObject); } else { Instance = this; } DontDestroyOnLoad(gameObject); stone = FindObjectOfType<SavePoint>(); } public void RespawnPlayer() { SaveData.Instance.LoadStone(); if(SaveData.Instance.stoneSceneName != null) { SceneManager.LoadScene(SaveData.Instance.stoneSceneName); } Debug.Log(SaveData.Instance.stonePos); if(SaveData.Instance.stonePos.x != 0 && SaveData.Instance.stonePos.y != 0) { respawnPoint.y = SaveData.Instance.stonePos.y + 1.358f; respawnPoint.x = SaveData.Instance.stonePos.x; } else { respawnPoint = new Vector2(-3f, -2.58f); } PlayerMovement.Instance.transform.position = respawnPoint; StartCoroutine(UIManager.Instance.DeactivateDeathScreen()); PlayerLife.pl.Respawn(); } }
UIManager code:
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class UIManager : MonoBehaviour { [SerializeField]Slider slider; [SerializeField]PlayerLife player; public static UIManager Instance; [SerializeField] GameObject deathScreen; public GameObject inventory; public SceneFader sceneFader; private void Awake() { if(Instance != null && Instance != this) { Destroy(gameObject); } else { Instance = this; } DontDestroyOnLoad(gameObject); sceneFader = GetComponentInChildren<SceneFader>(); } public IEnumerator ActivateDeathScreen() { yield return new WaitForSeconds(0.8f); StartCoroutine(sceneFader.Fade(SceneFader.FadeDirection.In)); yield return new WaitForSeconds(0.8f); deathScreen.SetActive(true); } public IEnumerator DeactivateDeathScreen() { yield return new WaitForSeconds(0.2f); deathScreen.SetActive(false); StartCoroutine(sceneFader.Fade(SceneFader.FadeDirection.Out)); slider.value = player.maxHealth; } // Start is called before the first frame update void Start() { slider.maxValue = player.maxHealth; slider.value = player.maxHealth; } public void UpdateUIHealtbar(int currentHealth) { slider.value = currentHealth; } }
Thanks in advance to everyone
April 17, 2024 at 6:52 pm #13921::If you are able to, could you record a video/screenshot of:
1) Your player dying and respawning
2) Dying and respawning all in one scene without prior save files.
3) The inspector of both UIManager & Player scripts while dying.My theory is that from your error, NullReferenceException, something is not assigned/found correctly. That something is then directed in the following line “UIManager+
d__8.MoveNext () (at Assets/Scripts/UIManager.cs:45)” meaning the error involves your UIManager.cs, DeactivateDeathScreen()
method in line 45. which would be this:
slider.value = player.maxHealth;
Check for 2 things here:
1) Check if the slider & player is set in the inspector of the UIManager.
2) Check that the slider/Player is set active while deactivate deathscreen is functioning. [Likely the script is trying to set the slider but the slider/player is not currently active while trying to set it.As for the Save point situation,
I have found issues with dying outside of the scene that the savepoint is set. If you die while outside of the scene you seem to respawn at the transition point in between scenes instead of the bench. I will have to test this out for a fix but otherwise, check if you respawn correctlly if you die in the same scene as the bench.April 17, 2024 at 8:01 pm #13924::Ok, here are the video:
1) https://imgur.com/a/BYON0dv
2) https://imgur.com/a/1tCnO5c
3) https://imgur.com/a/MkCBwpT (in the player inspector it doesn’t change anything)Yeah, in the UIManager the player script became missing for some reasons.
When i tried without doing the saving part (so just with the interaction with the bench) it worked fine
if(stone != null) { if (stone.interacted) { respawnPoint.y = stone.transform.position.y + 1.358f; respawnPoint.x = stone.transform.position.x; } else { respawnPoint = new Vector2(-3f, -2.58f); } } else { respawnPoint = new Vector2(-3f, -2.58f); }
April 17, 2024 at 8:55 pm #13925::I don’t know which part of the code you changed, however the issue should be that your Player does not include
DontDestroyOnLoad(gameObject);
inAwake()
orStart()
[We put it inAwake()
for this series].The point of
DontDestroyOnLoad(gameObject);
is to allow you to change scenes/reload scenes with the same gameobjects [Player + Menu + Other essential Managers].
Thus, when the scene is reloaded, the Player is destroyed and the Player instance called by your UIManager and other scripts lose the Player and cannot call or set anything with the Player as they are not set again after reloading the scene.
Similarly, since your Player isn’t following the scene change, when you reloaded the current scene, they “spawn” at their start point because that’s their scene start position with the reload scene.Thus, simply put the code in and it should work. If it doesn’t I’ll need a bit of time to test to see what other issue it could be.
April 17, 2024 at 10:34 pm #13927::Now it works perfectly! Thanks a lot, i wasted 2 days trying to figure it out why it didn’t work.
April 17, 2024 at 10:46 pm #13929::Great to hear! If you have any other issues always watch out for the scene Console and it’s error messages.
We have a post for NullReferenceException if you want to take a look at it:
What NullReferenceException errors are (and how to fix them) in Unity
Otherwise, if you can’t figure it out for this series, you can make another question post on the forum.
-
AuthorPosts
- You must be logged in to reply to this topic.
Advertisement below: