Forum begins after the advertisement:
[General] Issue with jumping, walljumping, bat and some questions
Home › Forums › Video Game Tutorial Series › Creating a Metroidvania in Unity › [General] Issue with jumping, walljumping, bat and some questions
- This topic has 5 replies, 2 voices, and was last updated 5 months ago by See hsyshsb Dnxnbdh.
-
AuthorPosts
-
July 29, 2024 at 12:32 am #15402::
Hello, currently I’m finishing part 9 of your tutorial and throughout following it I’ve ran into a few issues I couldn’t find answers for here on forum for and also got a few questions myself.
1. So the first thing is an error I’m receiving in the console as soon as I hit play for the first time after opening the project.
My UIManager script that the error mentions looks like that:
<code>using System.Collections; using UnityEngine; public class UIManager : MonoBehaviour { public static UIManager Instance; public SceneFader sceneFader; [SerializeField] GameObject deathScreen; public GameObject mapHandler; public GameObject inventory; private void Awake() { if (Instance != null && Instance != this) { Destroy(gameObject); } else { Instance = this; } <strong>DontDestroyOnLoad(gameObject);</strong> sceneFader = GetComponentInChildren<SceneFader>(); } public IEnumerator ActivateDeathScreen() { yield return new WaitForSeconds(0.8f); StartCoroutine(sceneFader.Fade(SceneFader.FadeDirection.In)); yield return new WaitForSeconds(0.8f); deathScreen.SetActive(true); } public IEnumerator DeactivateDeathScreen() { yield return new WaitForSeconds(0.5f); deathScreen.SetActive(false); StartCoroutine(sceneFader.Fade(SceneFader.FadeDirection.Out)); } } </code>
2. My bat enemy gets stunned even when I set stun duration to 0 and he also gets knockbacked and stunned after his hp reaches 0 (which I believe shouldn’t happen?)
Here’s my bat script:
<code>using UnityEngine; public class Bat : Enemy { [SerializeField] private float chaseDistance; [SerializeField] private float stunDuration; float timer; protected override void Start() { base.Start(); ChangeState(EnemyStates.Bat_Idle); } protected override void Update() { base.Update(); if (!PlayerController.Instance.pState.alive) { ChangeState(EnemyStates.Bat_Idle); } } protected override void UpdateEnemyStates() { float distance = Vector2.Distance(transform.position, PlayerController.Instance.transform.position); switch (GetCurrentEnemyState) { case EnemyStates.Bat_Idle: rb.velocity = new Vector2(0, 0); if (distance < chaseDistance) { ChangeState(EnemyStates.Bat_Chase); } break; case EnemyStates.Bat_Chase: rb.MovePosition(Vector2.MoveTowards(transform.position, PlayerController.Instance.transform.position, Time.deltaTime * speed)); FlipBat(); if (distance > chaseDistance) { ChangeState(EnemyStates.Bat_Idle); } break; case EnemyStates.Bat_Stunned: timer += Time.deltaTime; if (timer >= stunDuration) { ChangeState(EnemyStates.Bat_Idle); timer = 0; } break; case EnemyStates.Bat_Death: Death(Random.Range(5,10)); break; } } public override void EnemyHit(float damageDealt, Vector2 hitDirection, float hitForce) { base.EnemyHit(damageDealt, hitDirection, hitForce); if (health > 0) { ChangeState(EnemyStates.Bat_Stunned); } else { ChangeState(EnemyStates.Bat_Death); } } protected override void Death(float destroyTime) { rb.gravityScale = 12; base.Death(destroyTime); } protected override void ChangeCurrentAnimation() { anim.SetBool("Idle", GetCurrentEnemyState == EnemyStates.Bat_Idle); anim.SetBool("Chase", GetCurrentEnemyState == EnemyStates.Bat_Chase); anim.SetBool("Stunned", GetCurrentEnemyState == EnemyStates.Bat_Stunned); if(GetCurrentEnemyState == EnemyStates.Bat_Death) { anim.SetTrigger("Death"); int LayerIgnorePlayer = LayerMask.NameToLayer("Ignore Player"); gameObject.layer = LayerIgnorePlayer; } } void FlipBat() { if(PlayerController.Instance.transform.position.x < transform.position.x) { sr.flipX = true; } else { sr.flipX = false; } } } </code>
3. My player jumping method seems to be malfunctioning as sometimes when I barely tap jump button, the character jumps very high as shown in the video below:
My jumping method:
<code>private void Jump() { if (!pState.jumping && jumpBufferCounter > 0 && coyoteTimeCounter > 0) { rb.velocity = new Vector3(rb.velocity.x, jumpForce); pState.jumping = true; } if (!IsGrounded() && airJumpCounter < maxAirJumps && Input.GetButtonDown("Jump") && unlockedDoubleJump) { pState.jumping = true; airJumpCounter++; rb.velocity = new Vector3(rb.velocity.x, jumpForce); } if (Input.GetButtonUp("Jump") && rb.velocity.y > 3) { rb.velocity = new Vector2(rb.velocity.x, 0); pState.jumping = false; } rb.velocity = new Vector2(rb.velocity.x, Mathf.Clamp(rb.velocity.y, -maxFallingSpeed, rb.velocity.y)); anim.SetBool("Jumping", !IsGrounded()); }</code>
4. Walljumping seems to be working as intended when the wall I’m walljumping on is on the right side, while when I’m walljumping on left-side wall it’s working in a wrong way
My walljumping method:
<code>private void WallJump() { if (isWallSliding) { isWallJumping = false; wallJumpingDirection = !pState.lookingRight ? 1: -1; CancelInvoke(nameof(StopWallJumping)); } if (Input.GetButtonDown("Jump") && isWallSliding) { isWallJumping = true; rb.velocity = new Vector2(wallJumpingDirection * wallJumpingPower.x, wallJumpingPower.y); dashed = false; airJumpCounter = 0; pState.lookingRight = !pState.lookingRight; transform.eulerAngles = new Vector2(transform.eulerAngles.x, 180); Invoke(nameof(StopWallJumping), wallJumpingDuration); } } private void StopWallJumping() { isWallJumping = false; transform.eulerAngles = new Vector2(transform.eulerAngles.x, 0); rb.velocity = new Vector2(rb.velocity.x, 0); }</code>
5. If I put a transition to the other scene in a place that’s being “operated” by camera that is not the default one on the current scene, how do I make it so when I return from that other scene to the first scene, the active camera is set to the one where the scene transition is at (place that is not being “operated” by scene’s default camera)? You can see what I mean on the video below:
6. How to code the ability to unpause the game using esc key except only just pressing resume button with your mouse?
July 29, 2024 at 12:36 am #15403::Sorry, I’m posting for the first time and images and videos don’t work so I’ll just paste the imgur links:
July 29, 2024 at 10:22 am #15405::Hi there, I’ll try to help you best as i can but some of these issues seem a bit out of the ordinary.
- I am unfamiliar with this error message, but from my online research it’s to do with your UIManager/Canvas being toggled off on it’s scene visibility.
You can check up this thread for other people encountering the same issue and having it work after making their gameobject visible: https://discussions.unity.com/t/what-is-the-reason-of-this-error/763400/6
- Theoretically, your bat should be fine, the only difference in code, aside from naming, is just that the if statement for your stunned state uses
timer >= stunDuration
compared to ourtimer > stunDuration
. But eitherway, it shouldn’t affect this.
The only advice i could offer is to try resetting the bat’s components by removing and readding them onto the prefab. In this situation i can’t quite tell how to fix it, but the best we can do is modify the code to prevent it.
For now, you can change your Death state’s code to include the same code as the idle state for changing the bat’s velocity to 0,
rb.velocity = new Vector2(0, 0);
. This should allow your bat not to be knockbacked during death and have a way to stop said knockback should it happen.Next, you can change your stunned if statement to include an additional condition to check if the stunduration is 0,
if (timer >= stunDuration || stunDuration = 0)
.
- This is an issue that was faced a while ago and while i don’t have the exact details readily i can say that it’s likely due to the update rate in unity.
Unity is not fast enough to catch you letting go of the jump button at certain times, especially when it’s a fast tap, thus the
GetButtonUp
function, inif (Input.GetButtonUp("Jump") && rb.velocity.y > 3)
, might not activate as intended.So one thing you can try is to use
!GetButton
instead. Using that you can check for when the player is not holding dow2wn the jump button instead of when they release it. Although i feel there could possibly be some issues with it, try this code regardless and check for any further issues.
- This is something i may need to rework for the series due to the
Flip()
function itself causing this issue, at least in regards to you flipping/rotation of your character to face the opposite side.
Since the
Flip()
method controls the euler angles as of Part 8, the flipping mechanic of walljumping is jeapordized. Now, we should re-implement the usage of changing the value of which the player turns to depend on where the player is facing. To do this we’ll use the same idea as the way we set our wallJumpingDirection.private void WallJump() { if (isWallSliding) { isWallJumping = false; wallJumpingDirection = !pState.lookingRight ? 1: -1; CancelInvoke(nameof(StopWallJumping)); } if (Input.GetButtonDown("Jump") && isWallSliding) { isWallJumping = true; rb.velocity = new Vector2(wallJumpingDirection * wallJumpingPower.x, wallJumpingPower.y); dashed = false; airJumpCounter = 0; pState.lookingRight = !pState.lookingRight;
transform.eulerAngles = new Vector2(transform.eulerAngles.x, 180);float jumpRotation = pState.lookingRight ? 0: 180; transform.eulerAngles = new Vector2(transform.eulerAngles.x, jumpRotation) Invoke(nameof(StopWallJumping), wallJumpingDuration); } }Do tell me if this method works for you or if it doesn’t and i will update it accordingly with more effective code for it as i will test it out again at a later time.
- This one i might need some time to test out and make a new code for it.
But you can attempt to use a new script or the CameraManager script to do the same function as our SceneTransition script where we find the transition points that the player will be coming from, before setting the correct camera as the main camera.
Another weaker suggestion that won’t look as good since you’ll see the camera shift, is that you can make the camera bounds just a little bit more to the side of the scene transition entry and exit points, such that the player will collide with them as they enter/exit the bounds from their transition.
- Use
if (Input.GetKeyDown(KeyCode.Escape) && gameIsPaused)
to activate the resume method. Remember to put this function only in methods that are present with theUpdate()
method.
Again, do tell me what worked and what didn’t and I’ll give you another update response regarding your remaining issues. Hopefully my solutions works for you.
July 29, 2024 at 10:08 pm #15411::Thank you so much, your solutions for jumping and walljumping issues helped me, I haven’t noticed any problems after your fix, both work perfectly fine now. Also I managed to get rid of the error from 1. by deleting the library folder from my project and letting it create a new one, as someone mentioned in the thread you shared.
About bat issue, neither resetting the components of the prefab helped, nor changing the bat’s velocity to 0 on death state, nor adding another condition to stunned state. The bat still gets knockbacked after dying and gets stunned when stunDuration = 0.
About unpausing the game with escape key, I before tried adding the same line of code you suggested me, but this resulted in when I press escape, I see the pause menu but the game keeps running in the background, as if the timescale wouldn’t change to 0 and the gameIsPaused bool doesn’t change from false state at all. Also I cant press resume or return to main menu, the pause menu is stuck on my screen.
July 30, 2024 at 5:07 pm #15424::Bat Issue: After some testing, I’ve figured out the issue. The Enemy.cs
Update()
method stops theUpdateEnemyState()
when the enemy isRecoiling.This seems to align with how the bat is still stuck in it’s stunned state, and how the last hit onto the death state seems to push the Bat back in the same manner as the recoil knockback [The bat didn’t fall onto the ground but just horizontally].
Following this, I’ve realized that your recoil length is set to [2], thus meaning that your bat states cannot be updated until 2 seconds has passed, regardless of your stun duration. This only affects the Bat as we’ve given it a stunned state, unlike the Crawler or Charger. Thus, you just need to reduce the Recoil Length value on your Bat to less than your desired Stun Duration for your bat to be stunned for the correct time. [We use 0.1 as the recoil length, then set our stun duration to anything].
Resuming Game
The issue is that we didn’t actually make the escape button carry out the actual resume function properly. When we look into our Resume button’s function, we activated the
UIFadeOut()
function to remove the pause menu.private void Update() { if(Input.GetKeyDown(KeyCode.P)) { SaveData.Instance.SavePlayerData(); } if(Input.GetKeyDown(KeyCode.Escape) && !gameIsPaused) { pauseMenu.FadeUIIn(fadeTime); Time.timeScale = 0; gameIsPaused = true; } else if(Input.GetKeyDown(KeyCode.Escape) && gameIsPaused) { pauseMenu.FadeUIOut(fadeTime); UnpauseGame(); } }
Though, do check if you can still press the buttons even with this code. You may be facing another issue where you simply cant click the buttons. If you can’t do try checking if this solves the issue: https://blog.terresquall.com/2024/04/how-to-fix-an-unclickable-button-in-unitys-canvas-ui-system/
July 30, 2024 at 6:49 pm #15430 -
AuthorPosts
- You must be logged in to reply to this topic.