how to make your jump forgiving in unity 2d? - c#

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;
}
}

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?

JumpCount resets immediately after jumping 2D platformer

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!

Falling animation when on slopes

I'm pretty new to all of this so sorry for rookie mistakes.
I've built a State Machine that I'm pretty happy with, with just one problem, whenever the player jumps on a slope and keeps running (either up or down) the animation won't switch to running and stays at falling.
private void FixedUpdate()
{
GroundCheck();
if (state != State.hurt)
{
Movement();
DoubleJump();
StateMachine();
}
HurtCheck();
anim.SetInteger("state", (int)state);
}
private void Movement()
{
float hDirection = Input.GetAxis("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 StateMachine()
{
if(rb.velocity.y > 2f && isGrounded == false)
{
state = State.jumping;
}
if(rb.velocity.y < 2f && isGrounded == false)
{
state = State.falling;
}
if(rb.velocity.y == 0 && Mathf.Abs(rb.velocity.x) > 2f)
{
state = State.running;
}
if(rb.velocity.magnitude == 0)
{
state = State.idle;
}
}
It looks like you intend rb.velocity.y to be greater than 0 when on a slope. But in order to enter the running state you have a condition that rb.velocity.y == 0. If you want to run on a slope, then maybe you should change that condition like this.
if((rb.velocity.y < 2f) && (Mathf.Abs(rb.velocity.x) > 2f))
{
state = State.running;
}

transform.Rotate(0f, 180f, 0f); rotates the 2D sprite, but not it's children

I'm trying to achieve firing from a 2D Player, attached the "spawn point" and made it a child of the Player, when I try to flip the sprite it works, but it does not flip the "spawn point" so when I turn left, my "spawn point" is still looking right, so when I shoot, the bullets go to the left, not to the right.
Full script:
public class PlayerController : MonoBehaviour
{
void FixedUpdate()
{
RaycastHit2D hit = Physics2D.BoxCast(this.transform.position, new Vector2(0.4f, 0.1f), 0f, Vector2.down, groundCheckRadius, groundMask); //using this for a bigger and more accurate ground check
isTouchingGround = (hit.collider != null) ? true : false;
movementInput = Input.GetAxis("Horizontal");
CheckIfStuck(); //Checks if Mario is trying to walk into the wall and get stuck
if (!isDead)
{
if ((playerRigidbody2D.velocity.x > 0 && !isFacingRight) || (playerRigidbody2D.velocity.x < 0 && isFacingRight))
{
playerAnimator.SetBool("turning", true);
}
else
{
playerAnimator.SetBool("turning", false);
}
float movementForceMultiplier = Mathf.Max(maxHorizontalSpeed - Mathf.Abs(playerRigidbody2D.velocity.x), 1);
playerRigidbody2D.AddForce(new Vector2(movementInput * movementForce * movementForceMultiplier, 0));
playerRigidbody2D.velocity = new Vector2(Mathf.Clamp(playerRigidbody2D.velocity.x, -maxHorizontalSpeed, maxHorizontalSpeed), Mathf.Clamp(playerRigidbody2D.velocity.y, -maxVerticalSpeed, maxVerticalSpeed));
if (Input.GetKeyDown(KeyCode.Space))
{
if (isTouchingGround)
{
//Play Jump sound
if (!poweredUp)
audioSource.PlayOneShot(smallJumpSound);
else
audioSource.PlayOneShot(bigJumpSound);
isJumping = true;
playerRigidbody2D.velocity = new Vector2(playerRigidbody2D.velocity.x, jumpVelocity);
jumpTimeCounter = jumpTime;
}
}
if (jumpTimeCounter > 0 && isJumping)
if (Input.GetKey(KeyCode.Space))
{
jumpTimeCounter -= Time.deltaTime;
{
playerRigidbody2D.velocity = new Vector2(playerRigidbody2D.velocity.x, jumpVelocity);
}
}
if (Input.GetKeyUp(KeyCode.Space))
{
isJumping = false;
jumpTimeCounter = 0;
}
playerAnimator.SetFloat("movementSpeed", Mathf.Abs(playerRigidbody2D.velocity.x));
playerAnimator.SetBool("touchingGround", isTouchingGround);
}
if (movementInput > 0 && !isFacingRight)
{
FlipSprite();
}
else if (movementInput < 0 && isFacingRight)
{
FlipSprite();
}
}
void FlipSprite()
{
isFacingRight = !isFacingRight;
//Vector3 tempScale = transform.localScale;
//tempScale.x *= -1;
//transform.localScale = tempScale;
transform.Rotate(0f, 180f, 0f);
}
}
Flip method:
void FlipSprite()
{
isFacingRight = !isFacingRight;
//Vector3 tempScale = transform.localScale;
//tempScale.x *= -1;
//transform.localScale = tempScale;
transform.Rotate(0f, 180f, 0f);
}

Categories