Forum begins after the advertisement:
[Part 4 Bug Fixes] Heart UI, Mid-air Healing, moving while healing.
Home › Forums › Video Game Tutorial Series › Creating a Metroidvania in Unity › [Part 4 Bug Fixes] Heart UI, Mid-air Healing, moving while healing.
- This topic has 0 replies, 1 voice, and was last updated 6 months, 1 week ago by Joseph Tang.
-
AuthorPosts
-
May 9, 2024 at 6:05 pm #14578::
This is a supplementary post written for Part 4 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/05/creating-a-metroidvania-like-hollow-knight-part-4/
- Video Link: https://youtu.be/lO78OqaEDzA
Table of Contents
Missing Information in the Video
HitStopTime()
does not change with updated variables- Mana drains while “healing” mid-air
- Can carry out other actions while healing
Common 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.csHit()
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()
, moveyield return new WaitForSeconds(_delay);
to aboverestoreTime = true;
. - Change
WaitForSeconds
toWaitForSecondsRealtime
, 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’sTime.timeScale += Time.deltaTime * restoreTimeSpeed;
fromTime.deltaTime
toTime.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.deltaTimeTime.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
toGrounded()
. 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.jumpingGrounded() && !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();
inUpdate()
above the other functions while underif (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, addif (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.
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.
-
AuthorPosts
- You must be logged in to reply to this topic.
Advertisement below: