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 1 reply, 2 voices, and was last updated 3 weeks ago by A_DONUT.
-
AuthorPosts
-
July 29, 2024 at 12:23 am #15401::
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:
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)); } }
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?)
View post on imgur.com
Here’s my bat script:
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; } } }
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 jump method:
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()); }
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:
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); }
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:
View post on imgur.com
6. How to code the ability to unpause the game using esc key except only just pressing resume with your mouse?
November 27, 2024 at 8:23 pm #16576::Let’s go through each of your issues step-by-step:
1. Console Error in
UIManager
:The error might be related to how
DontDestroyOnLoad()
is interacting with other scripts or objects. Ensure thesceneFader
component is properly linked, and double-check if yourUIManager
object exists in the scene hierarchy.Potential fixes:
- Ensure that
SceneFader
is attached as a child object in the inspector. - Check for duplicate
UIManager
objects when the scene reloads. - Add
Debug.Log
to verify thesceneFader
assignment.
2. Bat Stun Issue:
Problem: The bat gets stunned even if
stunDuration
is set to 0 and also gets stunned/knockbacked after dying.Fixes:
-
Check stun logic:
InEnemyHit()
, ensure the bat only gets stunned if thestunDuration
is greater than zero:csharp if (health > 0 && stunDuration > 0) { ChangeState(EnemyStates.Bat_Stunned); } else if (health <= 0) { ChangeState(EnemyStates.Bat_Death); } <code></code>
-
Disable collision after death:
InDeath()
, ensure that the bat no longer processes hit logic or collisions:csharp protected override void Death(float destroyTime) { base.Death(destroyTime); rb.velocity = Vector2.zero; // Stop all movement rb.gravityScale = 12; GetComponent<Collider2D>().enabled = false; // Disable collisions } <code></code>
3. Jumping Too High:
Problem: The character sometimes jumps too high when you lightly tap the jump button.
Fix: Adjust the
Jump()
method to apply a minimum height and reduce velocity more smoothly:csharp if (Input.GetButtonUp("Jump") && rb.velocity.y > 3) { rb.velocity = new Vector2(rb.velocity.x, rb.velocity.y * 0.5f); // Reduce, but don't cancel instantly } <code></code>
Also, ensure
jumpBufferCounter
andcoyoteTimeCounter
are reset correctly after jumps.
4. Walljumping Issue (Directional Problems):
Problem: Walljumping works only on the right-side wall correctly.
Fix: Ensure the walljump direction logic is symmetrical:
csharp if (Input.GetButtonDown("Jump") && isWallSliding) { isWallJumping = true; float jumpDirection = pState.lookingRight ? -1 : 1; // Simplified for clarity rb.velocity = new Vector2(jumpDirection * wallJumpingPower.x, wallJumpingPower.y); Invoke(nameof(StopWallJumping), wallJumpingDuration); } <code></code>
Also, remove any unnecessary
transform.eulerAngles
adjustments unless flipping visually.
5. Camera Reset After Scene Transition:
Problem: Returning to a previous scene doesn’t set the correct camera position.
Fix: Store the current camera or position before transitioning:
csharp public Vector3 lastCameraPosition; // Before transitioning scenes lastCameraPosition = Camera.main.transform.position; // After loading the scene, reset the camera Camera.main.transform.position = lastCameraPosition; <code></code>
6. Unpause Game with
Escape
Key:Add an
Escape
key check in yourUpdate()
function:csharp void Update() { if (Input.GetKeyDown(KeyCode.Escape)) { if (gameIsPause) { unpauseGame(); // Unpause the game if it's already paused } else { // Existing code to pause the game pauseMenu.fadeUIIn(fadeTime); Time.timeScale = 0; gameIsPause = true; } } } <code></code>
These changes should address your issues. Let me know if you need further clarification or have more details to share! 😊
- Ensure that
-
AuthorPosts
- You must be logged in to reply to this topic.
Advertisement below: