JumpCount resets immediately after jumping 2D platformer - c#

I'm pretty new to all of this so sorry for rookie mistakes. I'm making a 2D platformer
I am checking for ground via RayCast and right after the player jumps, the jumpCounter resets to 0, so I get a bonus jump. I tried adding a 0.2s timer before it can reset but that caused trouble when jumping multiple times in a row (bunny hopping). Any help?
private void FixedUpdate()
{
GroundCheck();
if (state != State.hurt)
{
Movement();
DoubleJump();
StateMachine();
}
HurtCheck();
anim.SetInteger("state", (int)state);
}
private void Movement()
{
//Input.GetAxis returns a value between -1 up to 1
//Edit> Project Settings> Input> Axis> Horizontal
float hDirection = Input.GetAxisRaw("Horizontal");
//holding down "D" makes the value positive and vice versa
if (hDirection < 0)
{
rb.velocity = new Vector2(-speed, rb.velocity.y);
transform.localScale = new Vector2(-1, 1);
}
else if (hDirection > 0)
{
rb.velocity = new Vector2(speed, rb.velocity.y);
transform.localScale = new Vector2(1, 1);
}
else
{
}
if (Input.GetButtonDown("Jump") && isGrounded == true)
{
Jump();
}
}
private void Jump()
{
rb.velocity = new Vector2(rb.velocity.x, jumpforce);
state = State.jumping;
jumpCount += 1;
}
private void GroundCheck()
{
Debug.DrawRay(transform.position, Vector2.down * hitDistance, Color.green);
RaycastHit2D hit = Physics2D.Raycast(transform.position, Vector2.down, hitDistance, ground);
if(hit.collider != null)
{
isGrounded = true;
jumpCount = 0;
}
else
{
isGrounded = false;
}
}
private void DoubleJump()
{
if (Input.GetButtonDown("Jump") && isGrounded == false && jumpCount < 2)
{
rb.velocity = new Vector2(rb.velocity.x, jumpforce);
jumpCount += 1;
}
}

Hey Have you made sure your player's layer isn't ground layer or set ground layermask properly or maybe the hitDistance for the raycast is too high it should be very low like 0.1 or less or does jumpCount start from 0 or 1 try and alternate that or maybe have it start from two to lose the extra bonus jump...These would be where I would look, Good luck!

Related

Platformer Double-Jump and Dash Not Working

Working on a platformer where as the player moves over an energy orb, they can choose to fuel either a double jump or a dash. No errors according to unity, but when I press the corresponding keys for my double jump and dash, neither work. Simply nothing happens. Oh and btw my character randomly freezes and I have to tap the movement key again to get him to continue moving this is also a new issue so may be related. I am very new to all this.
public class playerMovement : MonoBehaviour
{
[SerializeField] private float speed;
[SerializeField] int dashEnergy = 1;
[SerializeField] int doubleJumpEnergy = 1;
private Rigidbody2D body;
private Animator anim;
private int jumpCount;
private void Awake()
{
body = GetComponent<Rigidbody2D>();
}
private void Update()
{
//Left-Right Movement
float horizontalInput = Input.GetAxis("Horizontal");
if(Input.GetKey(KeyCode.Space) && jumpCount == 0)
{
jump();
jumpCount += 1;
}
body.velocity = new Vector2(horizontalInput*speed, body.velocity.y);
//Character Turns Towards Movement Direction
if (horizontalInput > 0.01f)
transform.localScale = new Vector3(-5, 5, 5);
if (horizontalInput < -0.01f)
transform.localScale = new Vector3(5,5,5);
//Dash & doubleJump
void doubleJump()
{
if(Input.GetKey(KeyCode.Space)&&jumpCount==1 && doubleJumpEnergy==1)
{
jump();
doubleJumpEnergy -= 1;
}
}
void Dash()
{
if(Input.GetKey(KeyCode.LeftShift) && dashEnergy == 1)
{
body.velocity = new Vector2(horizontalInput*speed*60, body.velocity.y);
dashEnergy -=1;
}
}
}
public void jump()
{
body.velocity = new Vector2(body.velocity.x, speed);
}
private void OnCollisionEnter2D(Collision2D collision)
{
if(collision.gameObject.tag == "EnergyBubble" && Input.GetKey(KeyCode.V))
{
dashEnergy += 1;
}
if(collision.gameObject.tag == "EnergyBubble" && Input.GetKey(KeyCode.C))
{
doubleJumpEnergy += 1;
}
if (collision.gameObject.tag == "Ground")
{
jumpCount=0;
}
}
}
Firstly, all physics operations should be used from fixedUpdate method, for example:
void FixedUpdate()
{
if (Input.GetButtonDown("Space"))
rb.velocity = new Vector2(0, 10);
}
It's needs for smoothly physics movement.
Or call your own method from it:
void FixedUpdate()
{
if (Input.GetButtonDown("Space"))
jump();
}
Then you have a bug in condition check statements, you have to use:
//Dash & doubleJump
if (Input.GetKey(KeyCode.Space) && jumpCount == 1 && doubleJumpEnergy >= 1)
{
body.velocity = new Vector2(0, 2);
doubleJumpEnergy -= 1;
}
if (Input.GetKey(KeyCode.LeftShift) && dashEnergy >= 1)
{
body.velocity = new Vector2(horizontalInput * speed * 60, body.velocity.y);
dashEnergy -= 1;
}
Problem with a condition check statements, you need to have ">=" operator: dashEnergy >= 1 and doubleJumpEnergy >= 1 instead ==

Player constantly has a velocity of -7 on Y axis

I recently started making a new project and I'm still a beginner at coding. But recently I've made a jumping animation, and a falling animation. I've implemented those two things, and I made it so that if the Player has a velocity < 0 then activate falling anim. But, for some reason every time I press play the Player always has a velocity of -7 on the Y axis and never 0. Here's the code:
void OnMove()
{
Vector2 vec = actions.Movement.Move.ReadValue<Vector2>();
playerVelocity = new Vector2 (vec.x * speed, rb2d.velocity.y);
rb2d.velocity = playerVelocity;
}
void OnJump()
{
isGrounded = Physics2D.OverlapCircle(groundCheck.position, checkRadius, whatIsGround);
if(isGrounded)
{
animator.SetBool("isFalling", false);
}
if(isGrounded && actions.Movement.Jump.GetButtonDown())
{
isJumping = true;
jumpTimeCounter = jumpTime;
rb2d.velocity += new Vector2 (0f, jumpForce);
}
if(actions.Movement.Jump.GetButton() && isJumping == true)
{
animator.ResetTrigger("hasJumped");
animator.SetBool("isFalling", false);
animator.SetTrigger("hasJumped");
if (jumpTimeCounter > 0)
{
rb2d.velocity = new Vector2 (0f, jumpForce);
jumpTimeCounter -= Time.deltaTime;
animator.SetTrigger("hasJumped");
}
else
{
isJumping = false;
animator.SetBool("isFalling", false);
animator.ResetTrigger("hasJumped");
}
}
if(rb2d.velocity.y < 0)
{
animator.SetBool("isFalling", true);
}
}
Here's the inspector:
What am I doing wrong?

how to make your jump forgiving in unity 2d?

you know in good platform games the jump is forgiving like if you jumped and your collider isn't touching the ground after you touch the ground the player jump automatically I trayed to do it with a timer but some times the jump delays.
void Jump(bool isPressed)
{
if (isPressed && Ccollider2D.IsTouchingLayers(LayerMask.GetMask("Ground")))
{
rb.velocity = new Vector2(rb.velocity.x, 0f);
rb.velocity += new Vector2(0f, jumpForce);
}
else if (isPressed && Bcollider2D.IsTouchingLayers(LayerMask.GetMask("Ground")) && Ccollider2D.IsTouchingLayers(LayerMask.GetMask("Ground")) == false)
{
StartCoroutine(jumpWait());
}
}
IEnumerator jumpWait()
{
yield return new WaitForSeconds(0.08f);
if (Ccollider2D.IsTouchingLayers(LayerMask.GetMask("Ground")))
{
rb.velocity = new Vector2(rb.velocity.x, 0f);
rb.velocity += new Vector2(0f, jumpForce);
}
}
what is the actual method to do it
There’s no way for me to be sure of the function of Bcollider2D and Ccollider2D in your code, but for the timer you’d likely be better off using something like this:
float tryJumpTime = 0;
void Jump(bool isPressed)
{
if ( (isPressed || tryJumpTime > Time.time) && Ccollider2D.IsTouchingLayers(LayerMask.GetMask("Ground")))
{
rb.velocity = new Vector2(rb.velocity.x, 0f);
rb.velocity += new Vector2(0f, jumpForce);
}
else if (isPressed && Bcollider2D.IsTouchingLayers(LayerMask.GetMask("Ground")) && Ccollider2D.IsTouchingLayers(LayerMask.GetMask("Ground")) == false)
{
tryJumpTime = Time.time + 0.08f;
}
}

2D Jumping System not working correctly - Unity 2D

I was working on my 2D game in unity and i made this system to set the character to jump, and move around, but for some reason, i can only move mid air when i was moving on the ground, but if i stand still and then jump, i can not move mid air
Further Explaination: imagine you want to pick a coin in the air, and there is an obstacle under the coin, thus you have to jump while moving forward to pick it up, my problem is that you can only move mid air, if you were moving on the floor originally, but if you jump and THEN move right or left, the system just ignores it
My code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(Rigidbody2D))]
[RequireComponent(typeof(CapsuleCollider2D))]
public class CharacterController2D : MonoBehaviour
{
// Move player in 2D space
public float maxSpeed = 3.4f;
public float jumpHeight = 6.5f;
public float gravityScale = 1.5f;
public Camera mainCamera;
bool facingRight = true;
float moveDirection = 0;
bool isGrounded = false;
Vector3 cameraPos;
Rigidbody2D r2d;
CapsuleCollider2D mainCollider;
Transform t;
// Use this for initialization
void Start()
{
t = transform;
r2d = GetComponent<Rigidbody2D>();
mainCollider = GetComponent<CapsuleCollider2D>();
r2d.freezeRotation = true;
r2d.collisionDetectionMode = CollisionDetectionMode2D.Continuous;
r2d.gravityScale = gravityScale;
facingRight = t.localScale.x > 0;
if (mainCamera)
{
cameraPos = mainCamera.transform.position;
}
}
// Update is called once per frame
void Update()
{
// Movement controls
if ((Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.D)) && (isGrounded || Mathf.Abs(r2d.velocity.x) > 0.01f))
{
moveDirection = Input.GetKey(KeyCode.A) ? -1 : 1;
}
else
{
if (isGrounded || r2d.velocity.magnitude < 0.01f)
{
moveDirection = 0;
}
}
// Change facing direction
if (moveDirection != 0)
{
if (moveDirection > 0 && !facingRight)
{
facingRight = true;
t.localScale = new Vector3(Mathf.Abs(t.localScale.x), t.localScale.y, transform.localScale.z);
}
if (moveDirection < 0 && facingRight)
{
facingRight = false;
t.localScale = new Vector3(-Mathf.Abs(t.localScale.x), t.localScale.y, t.localScale.z);
}
}
// Jumping
if (Input.GetKeyDown(KeyCode.W) && isGrounded)
{
r2d.velocity = new Vector2(r2d.velocity.x, jumpHeight);
}
// Camera follow
if (mainCamera)
{
mainCamera.transform.position = new Vector3(t.position.x, cameraPos.y, cameraPos.z);
}
}
void FixedUpdate()
{
Bounds colliderBounds = mainCollider.bounds;
float colliderRadius = mainCollider.size.x * 0.4f * Mathf.Abs(transform.localScale.x);
Vector3 groundCheckPos = colliderBounds.min + new Vector3(colliderBounds.size.x * 1f, colliderRadius * 0.9f, 0);
// Check if player is grounded
Collider2D[] colliders = Physics2D.OverlapCircleAll(groundCheckPos, colliderRadius);
//Check if any of the overlapping colliders are not player collider, if so, set isGrounded to true
isGrounded = false;
if (colliders.Length > 0)
{
for (int i = 0; i < colliders.Length; i++)
{
if (colliders[i] != mainCollider)
{
isGrounded = true;
break;
}
}
}
// Apply movement velocity
r2d.velocity = new Vector2((moveDirection) * maxSpeed, r2d.velocity.y);
// Simple debug
Debug.DrawLine(groundCheckPos, groundCheckPos - new Vector3(0, colliderRadius, 0), isGrounded ? Color.green : Color.red);
Debug.DrawLine(groundCheckPos, groundCheckPos - new Vector3(colliderRadius, 0, 0), isGrounded ? Color.green : Color.red);
}
}```
if ((Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.D)) && (isGrounded || Mathf.Abs(r2d.velocity.x) > 0.01f))
In this line you check if you are grounded isGrounded or have some horizontal velocity Mathf.Abs(r2d.velocity.x) > 0.01f.
If you have any of those you give horizontal control.
So if you are moving horizontal en then jump Mathf.Abs(r2d.velocity.x) > 0.01f is true and gives you control in the air.
But if you are standing still and the jump isGrounded is false bequase you are in the air and Mathf.Abs(r2d.velocity.x) > 0.01f is false so you cant control your jump in the air.
If you always want control in the air remove the (isGrounded || Mathf.Abs(r2d.velocity.x) > 0.01f) check

Unity 5.1.1 skips "Input.GetKeyDown" line sometimes

I use Unity 5.1.1 on a Win 64 bit machine, more than capable to run what i'm creating of games. In the making of a 2D sidescroller, i found my character sometimes doesn't jump when prompted. Here is the code:
public float speed;
public float MomentAcc;
private float moveVertical;
private float score;
private float scoreP;
public GameObject wallRight;
public GUIText scoreText;
public bool touching;
void Start() {
MomentAcc = 10;
score = 0;
}
//Jump limiter
void OnCollisionStay2D() {
touching = true;
}
void OnCollisionExit2D() {
touching = false;
}
void Update() {
if (Input.GetKeyDown(KeyCode.W) && touching == true || Input.touchCount > 0 && Input.GetTouch (0).phase == TouchPhase.Began && touching == true) {
moveVertical = 29;
} else {
moveVertical = 0;
}
}
void FixedUpdate () {
scoreP = GameObject.Find ("Ball").GetComponent<Rigidbody2D> ().position.x + 11;
if(scoreP > score) {
score = score + 10;
}
UpdateScore ();
if(GetComponent<Death>().startGame == true) {
float moveHorizontal = 5;
Vector2 forward = new Vector2 (moveHorizontal, 0);
Vector2 jump = new Vector2 (0, moveVertical);
//Maxspeed limit
GetComponent<Rigidbody2D> ().AddForce (moveVertical * jump);
speed = moveHorizontal * MomentAcc * Time.deltaTime * 5;
if (GetComponent<Rigidbody2D> ().velocity.x < 7.000000) {
GetComponent<Rigidbody2D> ().AddForce (Vector2.right * speed);
if(GameObject.Find ("wallRight").GetComponent<wallRightScript>().wallJumpRight == true) {
GetComponent<Rigidbody2D> ().AddForce (new Vector2 (-420, 300));
}
if(GameObject.Find ("wallLeft").GetComponent<wallLeftScript>().wallJumpLeft == true) {
GetComponent<Rigidbody2D> ().AddForce (new Vector2(420, 150));
}
}
}
}
void UpdateScore() {
scoreText.text = "Score: " + (score );
}
}
(Sidenote: wallLeft/wallRight are for walljumping)
Here is your problem!
you are using Input.GetKeyDown(KeyCode.W) && touching == true in this case your jump is dependent on touching variable which can be false at the time when you press the "W" key. You are using rigidbody you cannot expect it to always colliding with ground when it is being dragged in horizontal. So you may need to change your implementation for ground check.
This Tutorial is good for learning about 2D character.
And one more advice! try to store reference of objects/components in some variables to access them easily. Using GetComponent<>/GameObject.Find() in Update()/FixedUpdate() is not efficient so not a good practice.

Categories