Here’s what’s happening during FixedUpdate().
First, you’re setting your velocity to have no vertical element.
rb.velocity = Vector2.right * speed;
Then, you add an arbitrary vertical force.
if (Input.GetKeyDown(KeyCode.UpArrow))
{
rb.AddForce(Vector2.up * force);
}
First, let's address the velocity itself. If you don't want to drift downward when directly setting a
Rigidbody's
velocity, you need to keep your vertical speed intact.
rb.velocity = new Vector2(speed, rb.velocity.y);
Furthermore, the distance your character is moving up when jumping right now is only a single physics calculation of movement before “floating” back down.
Second, there's the Input. You
DON'T want to use
Input.GetKeyDown() during
FixedUpdate(). Typically, this results in arbitrary inputs being missed. All Input instructions occur during
Update(), whereas
FixedUpdate() occurs with different timing. If you get two frames between a
FixedUpdate(), you'll miss the frame where the key was pressed. To be certain that the physics will be processed accurately, however, the best practice is to apply physics changes during
FixedUpdate().
bool jump = false;
void Update()
{
if(Input.GetKeyDown(KeyCode.UpArrow))
{
jump = true;
}
}
void FixedUpdate()
{
if(jump)
{
jump = false;
rb.AddForce(Vector2.up * rb.mass * force, ForceMode2D.Impulse);
}
}
Finally, the force itself. I tweaked it in my example above already, but here's what should change:
Right now, your jump force scales based on the physics update rate of your game. If you decide to turn it up or down, your character will jump lower or higher respectively. AddForce() (2D), by its default, applies force using ForceMode2D.Force. This results in a steady force that’s applied evenly per frame, with a goal of applying the designated force per-second. By this logic, if your physics update rate is the default of 50 FixedUpdate() cycles per second, your force of 300 scales down to 6 units-per-second immediate force applied. If you changed your physics rate to, say, 100 per second, then that 300 force scales down to only 3.
ForceMode2D.Impulse, however, applies its force instantaneously. I multiplied the force by the character’s mass to counteract that element of the equation. This results in a consistent force applied to the character when jumping, no matter their mass or physics rate.