- Home /
Raycasting not turning off jump. Would really love some help on my code.
Jumping works fine but i can jump mid air, even with this code .. where is the flaw in my code? thank you in advance.
[SerializeField] float throttle = 6f; // pawn speed [SerializeField] Rigidbody2D rb2d; [SerializeField] float jmpfrc = 300f;
public bool isGrounded = true;
void Start()
{
rb2d = GetComponent<Rigidbody2D>();
}
void Update()
{
//Debug.DrawRay(transform.position, new Vector2(0, -1), Color.red, .5f);
if (Input.GetAxis("Horizontal") > 0 || Input.GetAxis("Horizontal") < 0)
{
transform.position += transform.right * throttle * Time.deltaTime * Input.GetAxis("Horizontal");
}
// **** IF GROUNDED ***************************************************************
if (Physics2D.Raycast(transform.position, new Vector2(0, -1), .5f))
{
isGrounded = true;
}
else
{
isGrounded = false;
}
// **** END IF GROUNDED ***********************************************************
// **** JUMP **********************************************************************
if (Input.GetKeyDown(KeyCode.Space) && isGrounded == true)
{
rb2d.AddForce(transform.up * jmpfrc);
isGrounded = false;
}
// **** END JUMP ********************************************************************
}
Answer by WaqasHaiderDev · Jun 13, 2020 at 02:17 PM
I could understand your code and can checkout why raycasting is not working. But since you said your main aim is to stop mid air jump, I would recommend using vertical velocity check instead of raycasting. Something like this should work
// **** JUMP **********************************************************************
if (Input.GetKeyDown(KeyCode.Space) && rb2d.velocity.y == 0)
{
rb2d.AddForce(transform.up * jmpfrc);
}
// **** END JUMP ********************************************************************
also instead of calling physics functions in update, try to always call them in fixed update. Because update function depends on game performance on certain mobile which is measured in FPS so update depends on rendering FPS but fixed update will call after each 0.02 seconds (or whatever is set in physics settings in project settings). So a better modified form should be
[SerializeField] float throttle = 6f; // pawn speed
[SerializeField] Rigidbody2D rb2d;
[SerializeField] float jmpfrc = 300f;
public bool jump = false;
void Start()
{
rb2d = GetComponent<Rigidbody2D>();
}
void Update()
{
if (Input.GetAxis("Horizontal") > 0 || Input.GetAxis("Horizontal") < 0)
{
transform.position += transform.right * throttle * Time.deltaTime * Input.GetAxis("Horizontal");
}
// **** JUMP **********************************************************************
if (Input.GetKeyDown(KeyCode.Space) && rb2d.velocity.y == 0)
{
jump = true;
}
// **** END JUMP ********************************************************************
}
void FixedUpdate()
{
jump = false;
rb2d.AddForce(transform.up * jmpfrc);
}
I like your answer, thank you kindly for the help. I still would like to know why the raycasting isn't working, it really bugs me.
Hi, I never worked before with 2D raycasting but I am using 3D raycasting in my project. But however I tried your code and here are outcomes.
Basically your Ray is colliding with your player collider also and hence even if it is in air, it is still detecting a collider. And reporting IsGrounded as true. So what you can do is either use a layer $$anonymous$$ask, or use raycast hit information and check if it is detecting required colliders. Below is the approach.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TRY : $$anonymous$$onoBehaviour
{
[SerializeField] float throttle = 6f; // pawn speed
[SerializeField] Rigidbody2D rb2d;
[SerializeField] float jmpfrc = 300f;
private RaycastHit2D raycastHit2D;
public bool isGrounded = true;
// Start is called before the first frame update
void Start()
{
rb2d = GetComponent<Rigidbody2D>();
}
void Update()
{
Debug.DrawRay(transform.position, new Vector2(0, -20), Color.red, .5f);
if (Input.GetAxis("Horizontal") > 0 || Input.GetAxis("Horizontal") < 0)
{
transform.position += transform.right * throttle * Time.deltaTime * Input.GetAxis("Horizontal");
}
// **** IF GROUNDED ***************************************************************
raycastHit2D = Physics2D.Raycast(transform.position, new Vector2(0, -20), 0.5f);
if (raycastHit2D.collider.gameObject.layer == Layer$$anonymous$$ask.NameToLayer("YOUR REQUIRED LAYER NA$$anonymous$$E"))
{
isGrounded = true;
}
else
{
isGrounded = false;
}
// **** END IF GROUNDED ***********************************************************
// **** JU$$anonymous$$P **********************************************************************
if (Input.GetKeyDown(KeyCode.Space) && isGrounded == true)
{
rb2d.AddForce(transform.up * jmpfrc);
isGrounded = false;
}
// **** END JU$$anonymous$$P ********************************************************************
}
}
Or alternatively, the approach using layer mask is below
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TRY : $$anonymous$$onoBehaviour
{
[SerializeField] float throttle = 6f; // pawn speed
[SerializeField] Rigidbody2D rb2d;
[SerializeField] float jmpfrc = 300f;
public Layer$$anonymous$$ask groundLayer;
public bool isGrounded = true;
// Start is called before the first frame update
void Start()
{
rb2d = GetComponent<Rigidbody2D>();
}
void Update()
{
Debug.DrawRay(transform.position, new Vector2(0, -20), Color.red, .5f);
if (Input.GetAxis("Horizontal") > 0 || Input.GetAxis("Horizontal") < 0)
{
transform.position += transform.right * throttle * Time.deltaTime * Input.GetAxis("Horizontal");
}
// **** IF GROUNDED ***************************************************************
if (Physics2D.Raycast(transform.position, new Vector2(0, -20), 0.5f,groundLayer))
{
isGrounded = true;
}
else
{
isGrounded = false;
}
// **** END IF GROUNDED ***********************************************************
// **** JU$$anonymous$$P **********************************************************************
if (Input.GetKeyDown(KeyCode.Space) && isGrounded == true)
{
rb2d.AddForce(transform.up * jmpfrc);
isGrounded = false;
}
// **** END JU$$anonymous$$P ********************************************************************
}
}
And adjust the layer in inspector.
Now which approach is most suitable?
The first I told you using vertical velocity of rigid body because it will avoid casting rays in each update call and remembers casting rays are performance heavy. But out of two approaches of Layer mask or raycastHid2D, Layermask is more suitable because, it will only detect layers which will be assigned in layer mask otherwise raycast hit will first detect all layers and then it will detect if those colliders matches your layer.
If your question is answered, don't forget to accept the answer. Regards,
Also remember, the vertical velocity may be zero two times, once at ground and once at peak point. So it is better to include another check also. something similar
private void OnCollisionEnter2D(Collision2D collision)
{
if(collision.gameObject.layer == Layer$$anonymous$$ask.NameToLayer("YOUR GROUND LAYER NA$$anonymous$$E") && rb2d.velocity.y == 0)
{
isGrounded = true;
}
}
private void OnCollisionExit2D(Collision2D collision)
{
if (collision.gameObject.layer == Layer$$anonymous$$ask.NameToLayer("YOUR GROUND LAYER NA$$anonymous$$E"))
{
isGrounded = false;
}
}
And why so? Because this will ensure if player is touching ground while its velocity is zero only then IsGrounded should be true. Otherwise there may be case when player is jumping and its head is touching ground. So Ins$$anonymous$$d of single rigid body velcity check or is grounded check, Use this check.