- 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.