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

Viewing 1 post (of 1 total)
  • Author
    Posts
  • #14602
    Joseph Tang
    Moderator

    This is a supplementary post written for Part 5 of our Metroidvania series, and it aims to address 2 things:

    1. Missing information in the video, and;
    2. 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:


    Table of Contents

    Missing Information in the Video

    1. SceneFader NullReferenceException Error
    2. Player hit while in scene transition stops cutscene

    Common Issues

    1. Errors after transitioning scenes
    2. Player casts after healing

    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() to Awake() while leaving the code fadeOutUIImage = GetComponent<Image>(); the same.
        private void Start Awake()
        {
            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(), set pState.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 while pState.cutscene is true.
    • Finally, in SceneTransition.cs OnTriggerEnter2D(), set the player’s pState.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 of GetInputs(). This relocation ensures that the timer doesn’t reset when you release the Cast/Heal button before CastSpell() 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.

Viewing 1 post (of 1 total)
  • You must be logged in to reply to this topic.

Go to Login Page →


Advertisement below: