0
\$\begingroup\$

I'm using this code for Jump but when Space is hit, the character looks like they don't move. I played with JumpHeight and it turns out the jump does work; it just takes like 50f for it to finally visibly jump.

My Player's scale is 1 (1 x, 1 y, 1 z) so it's weird to me that a Jump Height of 7f isn't enough to make the character look like it's jumping at all. Is there something possibly deeper going on here?

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Jump : MonoBehaviour
{
    public float jumpHeight = 7f;
    public bool isGrounded;

    private Rigidbody rb;

    void Start()
    {
        rb = GetComponent<Rigidbody>();
    }

    void Update()
    {
        if (isGrounded)
        {
            if (Input.GetKeyDown("space"))
            {
                rb.AddForce(Vector3.up * jumpHeight);
                print("Space");
            }
        }
    }

    void OnCollisionEnter(Collision other)
    {
        if (other.gameObject.tag == "Ground")
        {
            isGrounded = true;
            print("IsGround");
        }
    }

    void OnCollisionExit(Collision other)
    {
        if (other.gameObject.tag == "Ground")
        {
            print("NoGround");
            isGrounded = false;
        }
    }
}

Player just has a Rigidbody with XYZ Rotation Constraints, and a capsule collider with a bottom that is sitting slightly above the Mesh's feet.

\$\endgroup\$
2
  • \$\begingroup\$ What's the mass of the rigid body? \$\endgroup\$
    – Vaillancourt
    Jul 6, 2021 at 0:52
  • \$\begingroup\$ 1 Mass, 0 Drag, 0.05 Angular Drag, Use Gravity checked, Is Kinematic Unchecked \$\endgroup\$
    – yunum
    Jul 6, 2021 at 0:53

1 Answer 1

3
\$\begingroup\$

Just because you name a variable "height" does not make it a measure of height.

The way you're using this variable, it is not a height but a force:

rb.AddForce(Vector3.up * jumpHeight);

So instead of representing a 7 meter rise, it represents a 7 Newton nudge.

1 Newton is enough force to accelerate a 1 kg object by \$1 \frac m {s^2}\$. And you apply this force for just one frame, which might be something like one sixtieth of a second.

So if your object has a mass of one kilogram, then seven Newtons applied for one frame accelerates it to a speed of \$7 \frac m {s^2} \cdot \frac 1 {60} s = \frac 7 {60} \frac m s = 0.11666... \frac m s\$ upward.

In that same time, the default gravity of \$-9.8 \frac m {s^2}\$ would accelerate your object to a speed of \$\frac {-9.8} {60} \frac m s = -0.16333... \frac m s\$ downward. This is greater than your upward velocity, so you do not attain a positive launch velocity to ever leave the ground.

This is grade 9 physics, so it really should not be a surprise that 7 Newtons is not enough to lift your object.

If you want to parametrize your jump with a height, a good way to do that is to use OnValidate to transform that height parameter into the corresponding physics push you need to achieve that height.

We can use the formula for the height of a vertically-launched projectile at time \$t\$:

$$ h(t) = h_0 + v_0 t + \frac g 2 t^2$$

Setting the derivative to zero gets us a formula for the time until we reach the apex of the parabola:

$$h^\prime(t) = v_0 + g t\\ 0 = v_0 + g t^*\\ -gt^* = v_0\\ t^* = \frac {v_0} {-g}$$

And substituting that into our original equation lets us solve for the initial velocity we need \$v_0\$, assuming an initial height of 0:

$$h(t) = h_0 + v_0 t + \frac g 2 t^2\\ h(t^*) = 0 + v_0 t^* + \frac g 2 {t^*}^2\\ h(t^*) = v_0 \frac {v_0} {-g} + \frac g 2 \frac {v_0^2} {g^2}\\ 2g h(t^*) = -2 v_0^2 + v_0^2 = -v_0^2\\ -2g h(t^*) = v_0^2\\ \sqrt{-2g h(t^*)} = v_0 $$

We'll take just the principal root since we know we're looking for an upward (positive) launch velocity.

Now we can write:

// Now this really truly does represent a height.
public float jumpHeight = 7f;

[SerializeField, HideInInspector]
private float _jumpVelocity;

void OnValidate() {
    // Compute the launch velocity needed to attain the requested height.
    _jumpVelocity = Mathf.Sqrt(-2f * Physics.gravity.y * jumpHeight);
}


void Update()
{
    if (isGrounded && Input.GetButtonDown("Jump")) {
        // Apply an instantaneous impulse to reach our launch velocity from rest.
        rb.AddForce(Vector3.up * _jumpVelocity, ForceMode.VelocityChange);
    }
}
\$\endgroup\$
1
  • \$\begingroup\$ I wish my account was old enough to vote this up. Thank you. \$\endgroup\$
    – yunum
    Jul 6, 2021 at 2:42

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .