Hello there, I am working on a 2D "platformer", I want the character to be able to double jump, and I want the jump to be always consistent with the jump height set in the editor. That means I wanna jump 5 units high whether the character is going up or going down, but the fact that the gravity is changing to make the game more snappy throws off the jump force calculations. Does any one of you know the solution to this problem?
#Inconsistent jump height when changing game gravity
1 messages · Page 1 of 1 (latest)
This is the code:
private void FixedUpdate() {
setGravity();
if (_input.intendedJump) {
jump();
return; // This is here to prevent double jump bug (according to some youtube video)
}
changeGravity();
}
private void setGravity() { // some physics formula for calculating gravity
Vector2 newGravity = new Vector2(0, (-2 * jumpHeight) / (jumpApexTime * jumpApexTime));
_RB2D.gravityScale = (newGravity.y / Physics2D.gravity.y) * defaultGravityMultiplier;
}
private void changeGravity() {
if (_RB2D.velocity.y > verticalVelocityEpsilon) {
defaultGravityMultiplier = upwardGravityMultiplier;
} else if (_RB2D.velocity.y < -verticalVelocityEpsilon) {
defaultGravityMultiplier = downwardGravityMultiplier;
} else {
if (_groundCheck.isGrounded) {
isJumping = false;
}
defaultGravityMultiplier = defaultGravity;
}
}
private void CalculateJumpForce() {
jumpForce = Mathf.Sqrt(-2f * Physics2D.gravity.y * _RB2D.gravityScale * jumpHeight); // "consistent" jump height in "unity units" depending on
jumpForce = (jumpForce - _RB2D.velocity.y);
}
private void jump() {
if (_groundCheck.isGrounded || (airJumpCounter < maxAirJumps) || (coyoteTimeCounter < coyoteJump && coyoteTimeCounter > 0.03f)) {
_input.intendedJump = false;
jumpBufferCounter = 0;
coyoteTimeCounter = 0;
CalculateJumpForce();
_RB2D.AddForce(Vector2.up * jumpForce, ForceMode2D.Impulse);
airJumpCounter++;
isJumping = true;
}
}
}
Hi @finite brook .
A solution for this problem has previously been provided here: https://discussions.unity.com/t/addforce-to-go-a-specific-distance-and-height/61013/2
Have a look and let me know if that works for you.
Unity Discussions
This is the so-called “ballistic trajectory”: an initial velocity is given to the projectile at certain elevation angle, and physics does the rest. The mass doesn’t matter, only the direction and magnitude of the initial velocity, thus it’s better to calculate the velocity vector and assign it directly to rigidbody.velocity. You can split the v...
In a nutshell, you want to set the target velocity rather than force in order to achieve the desired height, regardless of the object's mass. The gravity acceleration is taken into account in the calculation of the target velocity, and the velocity is decomposed into a horizontal (where gravity doesn't matter) and vertical component (where gravity does matter).
Based on that, i should remove the AddForce and exchange it for rb2d.velocity = vector2(rb2d.velocity.x, jumpForce) and the jumpForce should be calculated just like is, but without the other line?
(I tried that and it didnt help, the behaviour was the same)
It is quite surprising that the behavior is identical, since setting the velocity and adding a force (or impulse here) are two entirely different things, UNLESS the mass is 1 and you are applying the force when the current force is zero. Then the behavior would be the same.
So, I am seeing that you are changing gravity in your FixedUpdate function in the frames after having initiated the jump. This obviously invalidates the formula and you will not reach the intended height if the gravity is changed to a different value than what you used when calculating the force/velocity you are applying.
Yes, my mass is 1, and i dont think I'm applying any other force, so that's maybe why its the same.
I tried changing the order of the methods. (i think i tried every combination possible) and the jump is still inconsistent, but in a more consistent way if that makes any sense? 😅
This is the code now.
private void FixedUpdate() {
changeGravity();
setGravity();
CalculateJumpForce();
if (_input.intendedJump) {
jump();
return; // This is here to prevent double jump bug (according to some youtube video)
}
}
private void setGravity() { // some physics formula for calculating gravity
Vector2 newGravity = new Vector2(0, (-2 * jumpHeight) / (jumpApexTime * jumpApexTime));
_RB2D.gravityScale = (newGravity.y / Physics2D.gravity.y) * newGravityMultiplier;
}
private void changeGravity() {
if (_RB2D.velocity.y > verticalVelocityEpsilon) {
newGravityMultiplier = upwardGravityMultiplier;
} else if (_RB2D.velocity.y < -verticalVelocityEpsilon) {
newGravityMultiplier = downwardGravityMultiplier;
} else {
if (_groundCheck.isGrounded) {
isJumping = false;
}
newGravityMultiplier = defaultGravity;
}
}
private void CalculateJumpForce() {
jumpForce = Mathf.Sqrt(-2f * Physics2D.gravity.y * _RB2D.gravityScale * jumpHeight);
}
private void jump() {
if (_groundCheck.isGrounded || (airJumpCounter < maxAirJumps) || (coyoteTimeCounter < coyoteJump && coyoteTimeCounter > 0.03f)) {
_input.intendedJump = false;
jumpBufferCounter = 0;
coyoteTimeCounter = 0;
_RB2D.velocity = new Vector2(_RB2D.velocity.x, jumpForce);
airJumpCounter++;
isJumping = true;
}
}
I think i finally understood the issue.
The jumping is consistent and gravity behaves like its supposed to, but, when i was falling i had the downwardGravity applied, and with that I got the jump force, which was calculated correctly, but for the downward gravity, so the moment I jumped, the gravity switched to the "lighter" one but i was still using the force calculated for the strong gravity.
So the solution I came up with is just to simply calculate jump force always using the upward gravity scale, because i always wanna go up when i jump.
I don't know if that's a good or elegant solution, but it works. (so far i havent found a bug)