1
\$\begingroup\$

Since this wasn't clear enough, I've removed even more code. It kind of defeats the purpose I was aiming for, but I guess getting any answer relevant to the problem is better than none.

What I want: A cube to leave the ground with N velocity in the negative x direction, then gravity pulls it back down.

THE SETUP:

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

void Update() {

    //Jump
    if (Input.GetKeyDown("space"))
    {
        jump = true;
    }
}

TEST 1 (I really thought this should work as it was the solution I saw in so many google results)

void FixedUpdate()
{
    if (jump)
    {
        rb.AddForce(new Vector3(0, 0, -5000f));
        jump = false;
    }
}

TEST 2 (Added ForceMode.VelocityChange)

void FixedUpdate()
{
    if (jump)
    {
        rb.AddForce(new Vector3(0, 0, -5000f), ForceMode.VelocityChange);
        jump = false;
    }
}

TEST 3 (Tried other ForceModes)

void FixedUpdate()
{
    if (jump)
    {
        rb.AddForce(new Vector3(0, 0, -5000f), ForceMode./*INSERT OTHER ForceModes*/);
        jump = false;
    }
}

TEST 4 ( I know, changing velocity directly is a bad thing, but seeing as what I want is the cube to move upwards at a certain speed, it made sense to try it )

void FixedUpdate()
{
    if (jump)
    {
        var vel = rb.velocity;
        vel.z += -5000f;
        rb.velocity = vel;
        jump = false;
    }
}

It's been a long day, I'm sure I left some other attempts out.

Can someone explain to me why the cube is teleporting from Z=0 to Z= -2 (or some other value depending on the magnitude of the force)?

I can understand if it was something having to do with impact force not having enough time to change the velocity, but then why did the position change so drastically? And why didn't changing the velocity work, even though I know that is a bad way to go about it?

\$\endgroup\$
  • \$\begingroup\$ What do you want to happen exactly? Do you want a jump to suddenly increase the speed in an upwards direction and then let gravity make it go down again? In that case there are two answers describing that. What you're trying to achive with your code is hard to understand, it's certainly not gravity in the way Newton described it at least. If you want to reduce the speed in z-direction (which you seem to use as up) then you want to apply a consant force. Right now you're simulating something else. Wind resistance perhaps? \$\endgroup\$ – Mikael Högström Jun 15 '16 at 20:08
  • \$\begingroup\$ I'm trying to make a character jump. I don't know how much simpler I can say it. I want them to leave the ground with N velocity. I have tried adding a force in the desired direction, the result is an instantaneous change in position and no change in velocity. I've tried simply changing the velocity (YES I GET IT THAT'S A NO-NO BAD PROGRAMMER PLEASE MOVE ON) the result is the same, instantaneous change in position, no change in velocity. \$\endgroup\$ – R3D0 Jun 15 '16 at 20:37
  • \$\begingroup\$ I have used Uri's answer, and I get the same result seeing as it does exactly what I have already tried except worded differently. I just saw your updated answer, I have also tried that. I tried every version of ForceMode.XXXX that exists, they all either do the same thing or nothing at all. \$\endgroup\$ – R3D0 Jun 15 '16 at 20:40
1
\$\begingroup\$

Your problem comes from changing the velocity of the rigid body in a update. In my Spencerian this does not work at all. You have two solutions. Dont move your character with physics engine or use AddForce to move him. I changed your Fixedupdate to this and it works fine for me :

    void FixedUpdate()
    {
        float moveHorizontal = Input.GetAxis("Horizontal");
        float moveVertical = Input.GetAxis("Vertical");

        Vector3 movement = new Vector3(moveHorizontal,0, moveVertical);
        _rigidBody.AddForce (movement * speed);

        if (jump)
        {
            _rigidBody.AddForce(new Vector3(0, 500, 0));
            jump = false;
        }
}

Note I did not add ground checks and I use _rigidBody = GetComponent<Rigidbody>(); in the Start() method. Its a good tip not to use GetComponent in Update methods.

\$\endgroup\$
  • \$\begingroup\$ Other than the helpful tip of defining _rigidBody in the Start() method, you stated what I did up above, just in the y axis instead of the z axis. Is there some peculiarity that does not allow a proper "jump" in the z axis? I will re-orient my setup to test this. \$\endgroup\$ – R3D0 Jun 15 '16 at 15:46
  • 1
    \$\begingroup\$ what? No I did not state that. Notice how my solution does not use rigidbody.velocity. I have found that it constantly changes and messes up the physics. If you want physics based movement you should use AddForce for everything. My code jumps in the y axis because of my set up. If you have changed your gravity direction there is no problem jumping in the z axis. \$\endgroup\$ – Uri Popov Jun 15 '16 at 15:51
  • \$\begingroup\$ You use addforce for movement, which is not what I did, but it is also not what I am having issues with. You did in fact use addforce in your if(jump) line, which is nearly identical to the uncommented out section in my own if(jump) line. Or are you referring to the "gravity" section? I have tried it both ways, addforce and velocity, with no different results. I can change it to the other method if that would help, but it hasn't changed my own results in any way. \$\endgroup\$ – R3D0 Jun 15 '16 at 15:56
  • 1
    \$\begingroup\$ Look when you set the velocity of your rigid body in your movement logic you also set the SPEED of said rigidbody to 0 in the direction gravity faces. Thats why youe object falls slowly. Because your code and the physics engine are fighting. Just dont set velocity directly. Add forces to the rigidbody and the physics figure out the velocity. \$\endgroup\$ – Uri Popov Jun 16 '16 at 7:16
  • \$\begingroup\$ I agree... You're trying to fight the physics engine. Don't... \$\endgroup\$ – Mikael Högström Jun 16 '16 at 8:00
0
\$\begingroup\$

After several more hours working on it, I've narrowed it down to a bug/peculiarity in the Unity engine.

I deleted everything and started fresh, on doing so, the original code worked fine. During my attempts to replicate what I originally had, I found that adjusting the drag to something > 1 while either turning on/off the "Use Gravity" tickmark or changing the gravity from 0 to 9.81 or reverse between two runs caused the problem with no way to undo it.

As best I can tell, what happened was the cube moved at an incredible speed, seeming to teleport, but then was restricted to its maximum velocity in the second frame, then had its velocity reduced due to the gravity, making it stand still then fall. The slowness was also caused by the drag, which I managed to overcome by writing my own function to simulate the acceleration due to gravity, though this stopped working properly when I re-did the entire project, causing the cube to drop at incredible speeds as it no longer needed to overcome the 'invisible air resistance'.

Even after reducing drag back down to 0 this problem persists, meaning that although the surface to surface friction was returned to 0, the air drag was not.

This was done using Unity 5.3.5f1 (64-bit)

\$\endgroup\$
  • \$\begingroup\$ When you add velocity by forcemode velocity change, the unit is in m/s. I noticed you add 5000 m/s, this might as you say screw everything up in the physics engine with drag and may be the cause of your issue. Try setting drag, gravity and velocity changes to more normal values and see what happens. (drag < 1, gravity ~10N/kg, velocity 1-10 m/s) \$\endgroup\$ – Mikael Högström Jun 18 '16 at 8:31
0
\$\begingroup\$

Whenever you are using rigidbody to control movement you are handing over control to the physics engine. Unless you really know what you are doing, you should not set velocity (or position for that matter) explicitly if you are using the physics engine. It will result in unpredictable behaviour.

If you want to jump then ou should add force with ForceMode.Impulse as per documentation: Rigidbody.AddForce

Let the gravity control when the body should start moving down. If you want classic platformer behaviour like the Super Mario games you grew up with, remember that Mario's world has a higher gravity constant than 9.82 m/s as described in this very scientific analysis

The code posted by @Uri Popov should work, but, as stated I would use ForceMode.Impulse to be able to set a jump impulse that is defined in SI-units. If you want the user to be able to control the jump height by holding the jump button for different lengths of time then you want to use a force, i.e. ForceMode.Force for a variable length of time, say 0-0.5 seconds.

EDIT:

Ok you want the cube to get a certain velocity when jumping and then want gravity to affect it and make it go down?

Here's example code that makes that happen:

    void FixedUpdate()
    {
        float jumpVelocity = 5;//Meters per second
        if (jump && isGrounded())
        {
            _rigidBody.AddForce(new Vector3(0, jumpVelocity, 0), ForceMode.VelocityChange);
            jump = false;
        }
    }

Note that in this case I use the notation of y-axis being height, if you really really want to continue using z-axis then just apply the velocity change to that axis instead.

I think your problem is not in code per se, you need to read up on classical newtonian mechanics a bit before making a physics based game.

EDIT 2:

As you updated your answer again, I'll add another edit. Remember that the physics engine is using SI base units. This means that if you add a velocity change of 5000 that means you add 5000 m/s or 18000 km/h.

I think this may cause issues with the physics engine as the drag at those speeds will be enormous, and even if IRL drag would sooner or later reduce the speed to more sane values, in the discrete model in the engine with floating point errors and such maybe it could result in the body coming to a complete stop one frame later.

Try once more to do the same while first checking that all values are more "normal", i.e. gravity ~10 N/kg, drag < 1 and velocity changes 1-10 m/s. Also check that gravity is pointing the right direction (normal setting is negative y), and that the physics update step is about 0.02 s.

\$\endgroup\$
  • \$\begingroup\$ For Sanity's sake I've removed all reference to velocity even though --I ONLY USED IT FOR 2D MOVEMENT AND THAT WAS NOT THE PROBLEM-- I tried to use it as an alternative when the AddForce solution didn't work to show that I did try things before I came here. Sorry for the confusion, I thought people would read through the problem before giving the standard intro level response. \$\endgroup\$ – R3D0 Jun 15 '16 at 18:09
  • \$\begingroup\$ Yeah it's a pretty intro level question so don't be surprised (nor agitated) at getting intro level answers... \$\endgroup\$ – Mikael Högström Jun 15 '16 at 20:19
  • \$\begingroup\$ I've been working with this for months and this is the first time I've had trouble getting something to work. I've taken physics classes before, AP and University. I've used that exact solution already, and I get the same result. Instantaneous change in position, zero change in velocity. \$\endgroup\$ – R3D0 Jun 15 '16 at 20:30

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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