1
votes

There seem to be a fair amount of questions similar to this but none seem to really answer. I have a gameobject that can jump on a click of a button and automatically keeps going right.

I need the right moving motion to be constant but it ends up building faster and faster over time. If I use Velocity instead of AddForce, the motion is constant. But when I mouse click to jump, it takes like 10 over seconds to reach back down to ground.

Can I please get assistance on how I can keep the automatic movement to the right constant and still able to jump and reach back to ground fast. The following is my code. Thank you.

Edit:

Desired result

  • Gameobject constantly moving same speed to the right. When I jump, gameobject jumps and comes back down to ground over a period of 0.5 secs. Jump is expected to be like a smooth flow like a ball that jumps and comes back down smoothly.

Current result Using AddForce to move right

  • Gameobject starts to move right slowly and picks up speed over time getting faster and faster thus not able to keep constant same speed.

Current result Using Velocity to move right

  • Gameobject able to keep constant speed as wanted, but when I jump the Gameobject jumps and takes about 10 seconds to get back down to ground (It slowly glides back down).
public float jumpSpeed = 300;
 public float maxSpeed = 15; 
 Rigidbody rb;

 void Start()
 {
     rb = GetComponent<Rigidbody>();
     rb.velocity = Vector2.ClampMagnitude(rb.velocity, maxSpeed);
 }

 void Update()
 {
     if (Input.GetMouseButtonDown(0))
     {
         rb.AddForce(Vector3.up * jumpSpeed);
     }
 }

 void FixedUpdate()
 {
     rb.AddForce(Vector3.right * maxSpeed);
 }

//Trying to change velocity instead - Able to keep constant speed but when I jump, takes about 10 secs to get back down to ground. 

public float jumpSpeed = 2000;
public float maxSpeed = 5; 
Rigidbody rb;

void Start()
{
    rb = GetComponent<Rigidbody>();
    rb.velocity = Vector2.ClampMagnitude(rb.velocity, maxSpeed);
}

void Update()
{
    if (Input.GetMouseButtonDown(0))
    {
        rb.AddForce(Vector3.up * jumpSpeed);
    }
}

void FixedUpdate()
{
    rb.velocity = new Vector2(5, 0);
}
1
Update your code with the version of jump you did with velocity. I can help! - Programmer
I don't get you. Can you show me in code. - kar
You said "If I use Velocity instead of AddForce, the motion is constant." . That version of code you wrote with velocity instead of addforce is what I am looking for. Update your current code with that here and I will help. - Programmer
Can you describe how is current result different from desired result more precisely? Do you want the jump to happen faster? Also, you mention that you tried two different things in the question, but there's only one code sample. - Max Yankov
I have edited and added in the code where I change velocity instead for the right movement and also added in text to describe current and desired results - kar

1 Answers

2
votes

I think there are a few points of confusion here, so I'll answer some clarifying questions of my own.

Why does the speed of the object increase without bound when using add force?

The AddForce command will increase the velocity of the object every time you apply it. In the code, this means every call to FixedUpdate is increasing the velocity.

I think the misunderstanding is related to this line of code in your Start method:

rb.velocity = Vector2.ClampMagnitude(rb.velocity, maxSpeed);

Vector2.ClampMagnitude is not persistent. That is to say, it does not clamp the magnitude going forward. What you probably meant was to prevent the velocity from ever breaking "maxSpeed" in which case you should call the clamp method in FixedUpdate.

However, this would have a different effect which you might not intend. When the game object is moving along only one axis, the entire magnitude of the velocity is along that axis. Once the game object begins moving along a second axis, for instance while jumping, the magnitude of the velocity is split across both. This means that while your game object is jumping (has a y component to its velocity) its horizontal speed (the x component of its velocity) would be diminished. In other words, jumping would slow down your game object's movement to the right.

Why does my object "float" slowly downwards when setting the velocity directly?

One of the advantages of using AddForce is that it modifies the targeted axis of a vector without modifying the others. Setting the velocity directly is a little more tricky because you may accidentally clobber the velocity changes caused by physics.

For instance, in your FixedUpdate code:

rb.velocity = new Vector2(5, 0);

is setting the x velocity of your object to 5 - creating the smooth horizontal movement you want - but at the same time, setting the y velocity to 0.

This is why you needed to crank your jumpSpeed up to 2000 to see any effect on the object's height: it only has a split second to move upwards before the FixedUpdate method resets its upward motion to 0. This is also why your object appears to be "floating" back to earth. The internal physics engine is trying to apply gravity to the object but is being foiled by your code which constantly resets the objects downward velocity.

One Other Comment

I noticed you had some code in your Update method that was acting on the object's physics - that is your jump code. A good rule of thumb is to keep all the code working on an object's physics in the FixedUpdate method, since this is called just before the physics engine does it's work while the Update method is called just before the rendering engine does its work to draw the game.

One Possible Solution

The AddForce technique is normally recommended when working on an object's velocity because it creates natural looking physics through acceleration. Setting an objects velocity directly can create strange looking effects because objects in reality don't work this way. For instance, imagine what it would look like to see a car change from 0mph to 60mph in less than a split second.

If you check Unity's documentation on Rigidbody.velocity, you'll see they make this same recommendation, but add that jumping may be a scenario where you want to break this rule. However, as I mentioned earlier, we need to be careful when setting the y velocity explicitly so as to avoid changing the object's speed along other axes.

public float jumpSpeed = 2;
public float maxSpeed = 1; 
Rigidbody rb;

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

void FixedUpdate()
{   
    var newVelocity = rb.velocity;
    if (Input.GetMouseButtonDown (0))
        newVelocity.y = jumpSpeed;

    newVelocity.x = maxSpeed;

    rb.velocity = newVelocity;
}