Forum begins after the advertisement:
[Part 5] Missing Video Content, Common Issues & Fixes
Home › Forums › Video Game Tutorial Series › Creating a Metroidvania in Unity › [Part 5] Missing Video Content, Common Issues & Fixes
- This topic has 0 replies, 1 voice, and was last updated 4 months ago by
Joseph Tang.
-
AuthorPosts
-
May 10, 2024 at 3:17 pm #14602
Joseph Tang
Moderator::This is a supplementary post written for Part 5 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 convenience, below are the links to the article and the video:
- Article Link: https://blog.terresquall.com/2023/06/creating-a-metroidvania-like-hollow-knight-part-5/
- Video Link: https://youtu.be/cL6soESPqOc
Table of Contents
Missing Information in the Video
Common Issues
Missing Information in the Video
1. SceneFader NullReferenceException Error
[Caused by the SceneTransition script firing before the SceneFader is initialised.]
- In SceneFader.cs script, change
Start()
toAwake()
while leaving the codefadeOutUIImage = GetComponent<Image>();
the same.
private void
StartAwake() { fadeOutUIImage = GetComponent(); }
2. Player hit while in scene transition stops cutscene
[Caused by inefficient code that does not prevent player from taking damage while in cutscene]
- In PlayerController.cs
WalkIntoNewScene()
, setpState.invincibility
to true in the first line, and set to false in the last. - Then, add a line in
FlashWhileInvincible()
to prevent the player from flashing whilepState.cutscene
is true. - Finally, in SceneTransition.cs
OnTriggerEnter2D()
, set the player’spState.invincible
to true before loading scene.
PlayerController.cs
public IEnumerator WalkIntoNewScene(Vector2 _exitDir, float _delay) { pstate.invincible = true; //If exit direction is upwards if(_exitDir.y > 0) { rb.velocity = jumpForce * _exitDir; } //If exit direction requires horizontal movement if(_exitDir.x != 0) { xAxis = _exitDir.x > 0 ? 1 : -1; Move(); } Flip(); yield return new WaitForSeconds(_delay); pstate.invincible = false; pState.cutscene = false; } void FlashWhileInvincible() { if (pState.invincible && !pState.cutscene) { if(Time.timeScale > 0.2 && canFlash) { StartCoroutine(Flash()); } } else { sr.enabled = true; } }
SceneTransition.cs
private void OnTriggerEnter2D(Collider2D _other) { if (_other.CompareTag("Player")) { GameManager.Instance.transitionedFromScene = SceneManager.GetActiveScene().name; PlayerController.Instance.pState.cutscene = true; PlayerController.Instance.pState.invincible = true; StartCoroutine(UIManager.Instance.sceneFader.FadeAndLoadScene(SceneFader.FadeDirection.In, transitionTo)); } }
Common Issues
3. Errors after transitioning scenes.
[There are multiple problems that can arise from this, some listed here, that can be solved by a note found in the Forum Post:]
- 1. Mana isn’t being reset
- 2. Invincibility and time stop is non-functional
- 3. Hearts healed to full
Make sure that there is only one scene containing your Prefabs with singleton scripts such as the Player and Canvas. Entering a scene with a second singleton instance will cause NullReferenceException errors as scripts cannot differentiate or single out one script instance from multiple.
4. Player casts after healing.
[This is addressed in [Part 6] Article of the Metroidvania, but not in the video.]
In our PlayerController Script, let’s make a change to reset the castOrHealTimer in the
CastSpell()
method instead ofGetInputs()
. This relocation ensures that the timer doesn’t reset when you release the Cast/Heal button beforeCastSpell()
is called.PlayerController.cs
void GetInputs() { xAxis = Input.GetAxisRaw("Horizontal"); yAxis = Input.GetAxisRaw("Vertical"); attack = Input.GetButtonDown("Attack"); if (Input.GetButton("Cast/Heal")) { castOrHealTimer += Time.deltaTime; }
else { castOrHealTimer = 0; }} void CastSpell() { if (Input.GetButtonUp("Cast/Heal") && castOrHealTimer <= 0.05f && timeSinceCast >= timeBetweenCast && Mana >= manaSpellCost) { pState.casting = true; timeSinceCast = 0; StartCoroutine(CastCoroutine()); } else { timeSinceCast += Time.deltaTime; } if (!Input.GetButton("Cast/Heal")) { castOrHealTimer = 0; } if(Grounded()) { //disable downspell if on the ground downSpellFireball.SetActive(false); } ... }Note: Change the if parameter of both Heal() and CastSpell() to a higher float value if needed as 0.05f is a very limited time for a player to tap and fire a spell.
That will be all for Part 5.
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. -
AuthorPosts
- You must be logged in to reply to this topic.
Advertisement below: