1
\$\begingroup\$

So, I want to make an object jump an equal height whenever it touches the ground. Something like a bouncing ball. But I can't use Physics Materials. Here are some ways that I tried:

Used Physics.CheckSphere:

isGrounded = Physics.CheckSphere(rayPoint.position, grounDistance, groundLayer);

if(isGrounded )
{
    rb.AddForce(transform.up * jumpForce, ForceMode.Impulse);
}

Used Raycast:

bool groundHit = Physics.Raycast(rayPoint.position, -transform.up, rayDistance, groundLayer);
    
if(groundHit)
{
    rb.AddForce(transform.up * jumpForce, ForceMode.Impulse);
}
    

In each cases, the object jumps a different amount of height each time it reaches the ground. How can I make it jump an equal height each time?

\$\endgroup\$
3
3
\$\begingroup\$

Are you getting different results per jump on the same item, or are you trying to replicate the same height on different objects?

ForceMode.Impulse is dependent on the mass of the object you're using it on (https://docs.unity3d.com/ScriptReference/ForceMode.Impulse.html). If you want it to ignore the mass, ForceMode.VelocityChange (https://docs.unity3d.com/ScriptReference/ForceMode.VelocityChange.html) should do the trick.

Example:

if(groundHit)
{
    rb.AddForce(transform.up * jumpForce, ForceMode.VelocityChange);
}

Edit:

Something I didn't consider before this, how collisions are detected does appear to make a difference. If your Rigidbody is still falling when you trigger the "AddForce()" function, you'll be adding upward velocity with opposing downward force.

I used this example for detecting when my GameObject collided with the ground.

Slightly shortened, and changed "collision.contacts[0]" to "collision.GetContact(0)", the editor warns that the first one causes memory garbage. Using this, I got the same height every jump.

void OnCollisionEnter(Collision col)
{
    if(Vector3.Dot(col.GetContact(0).normal,Vector3.up) > 0.5)
    {
        isJumping = false;
    }
 }  

Per Evolor's comment, (which they should definitely turn into an answer so I can upvote it), you can set velocity directly instead of adding force.


Adding this to my answer since you asked about changing the local velocity of the rigidbody as well. The discussion there seems to explain doing that pretty well.

\$\endgroup\$
3
  • \$\begingroup\$ I am getting different results per jump on the same item. Even with ForceMode.VelocityChange there wasn't any change. However directly changing the rb.velocity.y worked for me. How can I change the local velocity of rigidbody? \$\endgroup\$ – Shromi Apr 27 at 18:34
  • 1
    \$\begingroup\$ @Shromi you mean like Evorlor's answer/comment? Maybe this link would help: answers.unity.com/questions/193398/… I was testing on an actual player controller. I wonder if you were getting those results because, as the ground was hit, it was immediately being sent upwards. So there would still be opposing force going down(?) negating your upward force. If you wanted to use your original code, maybe check to see if the x,y,z velocity is 0 before repeating? \$\endgroup\$ – Christopher H. Apr 27 at 20:55
  • 1
    \$\begingroup\$ Exactly! There was a different opposing force everytime it touched the ground. I solved the problem by adding rb.velocity.y==0 in the if statement. Now both velocity change and impulse works well. Thank you. \$\endgroup\$ – Shromi Apr 28 at 14:40
-1
\$\begingroup\$

Use Pos = S*T +(1/2)Gt^2 this formula

public class ABCD : MonoBehaviour
{
    float spd = 10;
    float t = 0;
    float g = -9.8f;

    private void Update()
    {
        t += Time.deltaTime;
        float y = spd * t + (1f / 2f) * g * (t * t);
        transform.position = new Vector3(0, y, 0);

        if(y < 0)
        {
            t = 0;
        }
    }
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.