Forum begins after the advertisement:


[Part 4] Missing Video Content, Common Issues & Fixes

Home Forums Video Game Tutorial Series Creating a Metroidvania in Unity [Part 4] Missing Video Content, Common Issues & Fixes

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

    This is a supplementary post written for Part 4 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. HitStopTime() does not change with updated variables
    2. Mana drains while “healing” mid-air
    3. Can carry out other actions while healing

    Common Issues

    1. Heart Interface Issues

    Missing Information in the Video

    1. HitStopTime() does not change with updated variables.

    Thanks to @‌mikedolt661 for pointing this out in the [Metroidvania Part 4] Youtube video, the HitStopTime() method does not work as intended with different casted values from the Enemy.cs Hit() method.
    This is due to wrong placement of a line and the complex issue of timeScales affecting Time values.

    • First, under PlayerController.cs IEnumerator StartTimeAgain(), move yield return new WaitForSeconds(_delay); to above restoreTime = true;.
    • Change WaitForSeconds to WaitForSecondsRealtime, this uses time that is unaffected by the frozen time scale and ensures that the set _delay value is reflected correctly.
    • Under void RestoreTimeScale(), change the if statement’s Time.timeScale += Time.deltaTime * restoreTimeSpeed; from Time.deltaTime to Time.unscaledDeltaTime. Similar to the previous step, this prevents the Time.deltaTime from being affected by the frozen time scale.
        void RestoreTimeScale()
        {
            if (restoreTime)
            {
                if (Time.timeScale < 1)
                {
                    Time.timeScale += Time.deltaTime Time.unscaledDeltaTime * restoreTimeSpeed;
                }
                else
                {
                    Time.timeScale = 1;
                    restoreTime = false;
                }
            }
        }
    
        IEnumerator StartTimeAgain(float _delay)
        {
            yield return new WaitForSecondsRealtime(_delay);
            restoreTime = true;
            yield return new WaitForSeconds(_delay);
        }

    Note: Since Time.deltaTime is unscaled, any high values (around 5+) for _restoreSpeed will not give a smooth transition from slow motion.


    2. Mana drains while “healing” mid-air.

    [This issue is caused by an inefficient code]

    • Set the Heal() function’s If statement’s !pState.jumping to Grounded(). This helps to check if the player is on the ground, instead of if they are jumping, before being able to heal.
        void Heal()
        {
            if (Input.GetButton("Healing") && Health < maxHealth && Mana > 0 && !pState.jumping Grounded() && !pState.dashing)
            {
                pState.healing = true;
                anim.SetBool("Healing", true);
    
                //healing
                healTimer += Time.deltaTime;
                if (healTimer >= timeToHeal)
                {
                    Health++;
                    healTimer = 0;
                }
    
                //drain mana
                Mana -= Time.deltaTime * manaDrainSpeed;
            }
            else
            {
                pState.healing = false;
                anim.SetBool("Healing", false);
                healTimer = 0;
            }
        }

    3. Can carry out other actions while healing.

    • In PlayerController.cs, move RestoreTimeScale();, FlashWhileInvincible();, Heal(); & Move(); in Update() above the other functions while under if (pState.dashing) return;.
    • Add if (pState.healing) return; below the 4 moved functions. This stops the rest of the functions from functioning while healing.
    • In Move() function, add if (pState.healing) rb.velocity = new Vector2(0, 0);. This stops the player from moving when healing is triggered.
        // Update is called once per frame
        void Update()
        {
            GetInputs();
            UpdateJumpVariables();
    
            if (pState.dashing) return;
            RestoreTimeScale();
            FlashWhileInvincible();
            Move();
            Heal();
            CastSpell();
            if (pState.healing) return;
            Flip();
            Jump();
            StartDash();
            Attack();
        }
    
        private void Move()
        {
            if (pState.healing) rb.velocity = new Vector2(0, 0);
            rb.velocity = new Vector2(walkSpeed * xAxis, rb.velocity.y);
            anim.SetBool("Walking", rb.velocity.x != 0 && Grounded());
        }

    Common Issues

    4. Heart Interface Issues.

    There are 3 possible different problematic layouts you may experience that we’ve listed here.

    a) There’s only 1 heart appearing/NullReferenceException Error.

    [This is most likely caused and solved by a note found in the Forum Post:]

    “Note that for the temp.transform.Find(“HeartFill”) portion, make sure that the string within Find() has the same name as the sprite in your project folder. For example, if your sprite is named “Hearts”, then you would use temp.transform.Find(“Hearts”) instead.”

    b) The Hearts only appear in the middle of my screen.

    • The Heart’s position is dependant on the location of your “Heart Parent” under the Canvas. Reposition the “Heart Parent” to your desired placement.

    Set the Rect Transform to Influence the Hearts’ Position.

    Note: The Hearts will appear from the left wall of the width of your “Heart Parent”, so take note of this consideration in the adjusted position of the GameObject.

    c) My Heart’s aren’t updating when i’m hit.

    [While there can be different reasons, this is the most common issue found]

    • Ensure that the “void SetFilledHearts()” function contains “if (i < PlayerController.Instance.Health)" and not "if (i < PlayerController.Instance.maxHealth)".
        void SetFilledHearts()
        {
            for (int i = 0; i < heartFills.Length; i++)
            {
                if (i < PlayerController.Instance.Health)
                {
                    heartFills[i].fillAmount = 1;
                }
                else
                {
                    heartFills[i].fillAmount = 0;
                }
            }
        }

    That will be all for Part 4.

    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: