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
- This topic has 0 replies, 1 voice, and was last updated 1 week, 4 days ago by Joseph Tang.
-
AuthorPosts
-
May 9, 2024 at 6:05 pm #14578Joseph TangModerator
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.
- 4. Heart Interface Issues.
*Common 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.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. - 1.
-
AuthorPosts
- You must be logged in to reply to this topic.
Advertisement below: