Forum begins after the advertisement:
[Part 7 Bug Fixes] New Game Error, Respawn Issues, Optimized Bench Interaction
Home › Forums › Video Game Tutorial Series › Creating a Metroidvania in Unity › [Part 7 Bug Fixes] New Game Error, Respawn Issues, Optimized Bench Interaction
- This topic has 2 replies, 3 voices, and was last updated 1 month, 1 week ago by
Terence.
-
AuthorPosts
-
May 10, 2024 at 6:57 pm #14619::
This is a supplementary post written for Part 7 of our Metroidvania series, and it aims to address 2 things:
- Missing information in the video, and;
- Address common issues / questions that readers run into, and possible solutions for these questions.
For this part, there are less bugs to be addressed, However, check this post to see if your issue is addressed there:
[Part 7] SceneFader NullReferenceException and SaveData EndOfStreamException
For convenience, below are the links to the article and the video:
- Article Link: https://blog.terresquall.com/2023/07/creating-a-metroidvania-like-hollow-knight-part-7/
- Video Link: https://youtu.be/hEEOefW3MHU
Table of Contents
Missing Information in the Video
- Starting fresh game causes player to not be able to land or load save data.
- Player respawns at 0 health after leaving game from death. + Moving Player corpse.
- Bench interaction is inconsistent.
- Capping Player falling speed.
Common Issues
- Unable to click on Respawn Button.
- Player spawns outside of map after updating `SaveData` (new 15 May 2025)
Missing Information in the Video
1. Starting fresh game causes player to not be able to land or load save data.
[Caused by
LoadPlayerData()
trying to load a save file when the player has never calledSavePlayerData()
, and thus prevents the rest ofStart()
to not be called.]- Move the called `LoadPlayerData()` to the bottom of `Start()`. This will make sure the rest of the `Start()` code is called and allows the player to play the game even if `LoadPlayerData()` fails.
- Move the if statement which checks for half mana, to below the `LoadPlayerData()`.
// Start is called before the first frame update void Start() { pState = GetComponent<PlayerStateList>(); rb = GetComponent<Rigidbody2D>(); sr = GetComponent<SpriteRenderer>(); anim = GetComponent<Animator>();
SaveData.Instance.LoadPlayerData();gravity = rb.gravityScale;if (halfMana) { UIManager.Instance.SwitchMana(UIManager.ManaState.HalfMana); } else { UIManager.Instance.SwitchMana(UIManager.ManaState.FullMana); }Mana = mana; manaStorage.fillAmount = Mana; Health = maxHealth; SaveData.Instance.LoadPlayerData(); if (halfMana) { UIManager.Instance.SwitchMana(UIManager.ManaState.HalfMana); } else { UIManager.Instance.SwitchMana(UIManager.ManaState.FullMana); } }
2. Player respawns at 0 health after leaving game from death. + Moving Player corpse.
[Caused by
SavePlayerData()
taking place after the death of the player, and not respawning to reset this fact.]- Add a code to PlayerController.cs `Start()` to call the `RespawnPlayer()` method in GameManager.cs, as well as set the `pState.alive` to false if the Player’s health is at [0]. This will respawn the player if they are loaded in with 0 health.
- In the `Death()` method, set the player’s `Rigidbody2D` to freeze position, and `BoxCollider2D` to false. This prevents the dead player from acting as a collider or being influenced by gravity to fall or be pushed by other moving entities to a scene transition.
- In the `Respawned()` method, reset the `Rigidbody2D` constraints and reenable the BoxCollider2D.
// Start is called before the first frame update void Start() { ... { UIManager.Instance.SwitchMana(UIManager.ManaState.FullMana); } if (Health == 0) { pState.alive = false; GameManager.Instance.RespawnPlayer(); } } IEnumerator Death() { ... anim.SetTrigger("Death"); rb.constraints = RigidbodyConstraints2D.FreezePosition; GetComponent[BoxCollider2D]().enabled = false; yield return new WaitForSeconds(0.9f); ... } public void Respawned() { if(!pState.alive) { rb.constraints = RigidbodyConstraints2D.None; rb.constraints = RigidbodyConstraints2D.FreezeRotation; GetComponent[BoxCollider2D]().enabled = true; pState.alive = true; ... } }
Note: The “[]” for BoxCollider2D are to be replaced by angle brackets, but I cannot use it on HTML.
3. Bench interaction is inconsistent.
[Caused by inefficient code, explanation in link below]
public class Bench : MonoBehaviour { bool inRange = false; public bool interacted; // Update is called once per frame 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(); Debug.Log("benched"); } }
private void OnTriggerStay2D(Collider2D _collision) { if(_collision.CompareTag("Player") && Input.GetButtonDown("Interact")) { 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(); Debug.Log("benched"); } }void OnTriggerEnter2D(Collider2D _collision) { if(_collision.CompareTag("Player")) inRange = true; } private void OnTriggerExit2D(Collider2D _collision) { if (_collision.CompareTag("Player")) { inRange = false; } } }
4. Capping Player falling speed.
- Set the player’s velocity in `Jump()` to it’s current velocity, but clamp the y value to a new variable, `maxFallingSpeed`.
[SerializeField] private int maxFallingSpeed; //max fall speed void Jump() { ... if (Input.GetButtonUp("Jump") && rb.velocity.y > 3) { pState.jumping = false; rb.velocity = new Vector2(rb.velocity.x, 0); } rb.velocity = new Vector2(rb.velocity.x, Mathf.Clamp(rb.velocity.y, -maxFallingSpeed, rb.velocity.y)); anim.SetBool("Jumping", !Grounded()); }
Common Issues
5. Unable to click on Respawn Button.
[This solution is only if you are unable to interact with the button (It is not highlighted/changes colour when hovered by mouse and cannot be clicked):]
- 1. Ensure that your Button is at the bottom of the Canvas Hierarchy [Move the game object with the button to the last position]. This will place your button in front of all other game objects in the canvas, preventing Raycast blocking.
- 2. Turn off “RayCast Target” on your other game objects.
- 3. Ensure your scene has an “EventSystem” component.
How to fix an unclickable Button in Unity’s Canvas UI system
That will be all for Part 7. Hopefully this can help you on any issues you may have. However, if you find that your issues weren’t addressed or is a unique circumstance, you can submit a forum post to go into detail on your problem for further assistance.
has upvoted this post. October 28, 2024 at 8:41 am #16197May 15, 2025 at 3:11 pm #18176::6. Player spawns outside of map after updating `SaveData`
If you’ve ever had an issue where, after updating your
SaveData
script to save more data, your player spawns outside the map and completely breaks the game like this:View post on imgur.com
Please check out this topic — this problem is explained in more detail.
[Part 7] Fix for game breaking when SaveData is edited
-
AuthorPosts
- You must be logged in to reply to this topic.
Advertisement below: