- Home /
Unity Character Not Moving Midair
When on the ground my character moves fine, but the velocity gets locked in a certain direction whenever I jump.
public class Player : MonoBehaviour { [SerializeField] float moveSpeed = 5f; [SerializeField] float maxSpeed = 2f; [SerializeField] float jumpScalar = 250f;
bool isOnGround;
Rigidbody2D rb;
private void Start()
{
rb = gameObject.GetComponent<Rigidbody2D>();
}
private void FixedUpdate()
{
Move();
Jump();
}
private void Move()
{
if (Mathf.Abs(rb.velocity.x) < maxSpeed)
{
rb.AddForce(new Vector2(Input.GetAxis("Horizontal") * moveSpeed, 0));
}
}
private void Jump()
{
if (Input.GetButtonDown("Jump") && isOnGround)
{
Vector2 jumpForce = new Vector2(0, jumpScalar);
rb.velocity = jumpForce;
}
}
private void OnCollisionEnter2D(Collision2D collision)
{
if (CollisionIsWithGround(collision))
{
isOnGround = true;
}
}
private void OnCollisionExit2D(Collision2D collision)
{
if (!CollisionIsWithGround(collision))
{
isOnGround = false;
}
}
private bool CollisionIsWithGround(Collision2D collision)
{
bool isWithGround = false;
foreach (ContactPoint2D c in collision.contacts)
{
Vector2 collisionDirectionVector = c.point - rb.position;
if (collisionDirectionVector.y < 0)
{
isWithGround = true;
}
}
return isWithGround;
}
}
Answer by DenisIsDenis · Jun 13, 2021 at 08:29 AM
There is no friction in the air, so the player doesn't slow down. Therefore, after exceeding the maximum speed, your condition in Move () will always return false.
Therefore, you need to check the speed after the application of force:
private void Move()
{
rb.AddForce(new Vector2(Input.GetAxis("Horizontal") * moveSpeed, 0));
if (Mathf.Abs(rb.velocity.x) > maxSpeed)
{
rb.AddForce(new Vector2(Input.GetAxis("Horizontal") * moveSpeed * (-1), 0));
}
}
So we cancel the force that increased the speed over the norm.
EDITED: @DinoSore69. I tested the script and modified it a bit to make it work:
private void Move()
{
rb.AddForce(new Vector2(Input.GetAxis("Horizontal") * moveSpeed, 0));
var xVel = rb.velocity.x;
xVel = Mathf.Clamp(xVel, -maxSpeed, maxSpeed);
rb.velocity = new Vector2(xVel, rb.velocity.y);
}
I also fixed the Jump() function so that the player has a fixed jump speed:
private void Jump()
{
if (Input.GetButton("Jump") && isOnGround)
{
rb.velocity = new Vector2(rb.velocity.x, jumpScalar);
}
}
And if you do not need the player to jump on the walls, then here is the modified script for defining isOnGround:
private bool CollisionIsWithGround(Collision2D collision)
{
bool isWithGround = false;
foreach (ContactPoint2D c in collision.contacts)
{
Vector2 collisionDirectionVector = c.point - rb.position;
// Change "30" to the angle you want
if (Vector2.Angle(collisionDirectionVector, Vector3.down) < 30)
{
isWithGround = true;
}
}
return isWithGround;
}
Thanks for the reply @DenisIsDenis, I implemented the code, but it didn't change the result at all. I still have no player movement while in the air.
Your answer