2D Platform irregular jump
Hello!
I just started Unity, I'm a software developer and never touched Unity before so don't kill me if you see some Unity fraude code haha :)
Anyways my problem is that my jumps are kind off irregular. When I tap my jump key, the jump is the same every time, but when I hold the jump key down I get irregular jump heights, but I can't figure out the problem.
Here's the code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CharacterController : MonoBehaviour {
private const float MAX_SPEED = 2f;
private const float BASE_SPEED = 1000f;
private const float BASE_JUMP = 100f;
private float _speedMod = 1f;
private float _jumpMod = 1f;
private bool _grounded = true;
private BoxCollider2D _cld;
private Rigidbody2D _rgbd;
void Start () {
_cld = GetComponent<BoxCollider2D> ();
_rgbd = GetComponent<Rigidbody2D> ();
_rgbd.drag = 3f;
}
void Update() {
_grounded = Grounded ();
}
void FixedUpdate () {
var hsp = 0f;
var vsp = 0f;
var move_h = Input.GetAxis ("Horizontal");
if(_rgbd.velocity.x <= MAX_SPEED && _rgbd.velocity.x >= -MAX_SPEED)
hsp = move_h * (BASE_SPEED * _speedMod) * Time.fixedDeltaTime;
if (_grounded && Input.GetKey (KeyCode.Space))
vsp = BASE_JUMP * _jumpMod;
_rgbd.AddForce(new Vector2(hsp, vsp));
}
bool Grounded(){
return Physics2D.Raycast (
new Vector2 (transform.position.x, transform.position.y - (_cld.size.y / 2 + 0.01f)),
Vector2.down,
distance: 0.01f
).collider != null;
}
}
I'm pretty sure it has to do with the raycast thing not being precise, but correct me if I'm wrong!
Answer by NoseKills · Jul 26, 2017 at 04:34 PM
I can see a couple reasons why the problem might be happening.
The docs say Input.GetKey returns true while the user holds down the key. As you said you are holding down the key, so the only limiting factor is _grounded
. How long the character is grounded depends on its initial velocity and position and perhaps the shape of the ground underneath so I don't think it's enough to guarantee you add the vertical force the same amount of times each jump.
You should consider for example using Input.GetKeyDown() which happens only once when they key is pressed so you always add the force just once each press. Perhaps even reset the vertical speed of the player rigidBody before this to get an identical starting situation for each jump
A fast player might still be able to press the key twice before _grounded
becomes false (if _grounded doesn't become false in 1 FixedUpdate), but there are other conditions you might consider e.g. allow jumping only after the jump has caused _grounded
to become false and then true again.
Another issue is that Input state can only change each frame (between Update calls). Depending on your frametrate, one Update call might consist of 0-n FixedUpdate calls. So even Input.GetKeyDown
might return true multiple times when you check it in FixedUpdate.
To fix this you could do something like
bool jumped;
void Update() {
if (Input.GetKeyDown(KeyCode.Space)) {
jumped = true;
}
}
void FixedUpdate () {
var hsp = 0f;
var vsp = 0f;
var move_h = Input.GetAxis ("Horizontal");
if(_rgbd.velocity.x <= MAX_SPEED && _rgbd.velocity.x >= -MAX_SPEED)
hsp = move_h * (BASE_SPEED * _speedMod) * Time.fixedDeltaTime;
if (_grounded && jumped) {
jumped = false;
vsp = BASE_JUMP * _jumpMod;
}
_rgbd.AddForce(new Vector2(hsp, vsp));
}