Forum begins after the advertisement:


[Part 4] Article Changes, Common Issues & Bugfixes

Home Forums Video Game Tutorial Series Creating a Metroidvania in Unity [Part 4] Article Changes, Common Issues & Bugfixes

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

    This is an update post to summarize the changes made to the content of the Metroidvania series.
    Additionally, this post is to compile and go through some common issues that viewers and readers may face when following the Metroidvania series, as well as some solutions that may fix or solve the issues.

    Some solutions given will also be under the assumptions that the code for the mechanic is 1:1 for the relevant part.

    In this post, we will go through:
    [Part 4]

      *Article Changes*

    • 1. HitStopTime() does not change with updated variables.
    • 2. Mana drains while “healing” mid-air.
    • 3. Infinite Attack Speed.
    • *Common Issues*

    • 4. Heart Interface Issues.


    [Part 4] Mana and Spellcasting

    Article Changes

    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: