- Home /
Why ForceMode.VelocityChange is inconsistent and how to fix it?
So i've created a simple test project with nothing in there but a camera, light and two cubes. I did not alter any physics settings (i did not alter any settings if that matters).
Both cubes have Rigidbodies attached. For cube number one it's almost default, only isKinematic is set to true, so it doesn't move. It acts like a ground.
Here's the cube number two: (Mass = 40; Drag = 1) - everything else - default;
As you can see, there is also "Jump" script attached to the second Cube. It's really simple:
public class jump : MonoBehaviour {
Rigidbody rb;
public float jumpHeight = 10;
void Awake()
{
rb = GetComponent<Rigidbody>();
}
void FixedUpdate()
{
if(Input.GetButtonDown("Jump"))
{
rb.AddRelativeForce(Vector3.up * jumpHeight, ForceMode.VelocityChange);
}
}
}
So, the problem is: every time i press "Space" i get kind of random jump height. Of course i used google to find a fix, but it got me nothing useful, in fact, all i got is complains about the same issue dated back to the year 2011. Any help will be appreciated.
Worth mentioning that i have to add force relatively to the object, hence the "AddRelativeForce".
are you getting different jump heights at the same position, or at different positions.
I had the same problem with my 2Dplatformer, where i was getting higher jumps if my cube was above '0 in y axis' & lower jumps when it was below 0 in y axis. (here y axis is y vertical axis & x axis is my horizontal axis) this is due to the
use gravity
property in your rigidbody.
i ended up implementing my own jump&gravity code for my player GameObject.
Answer by coykto · Dec 25, 2017 at 12:49 PM
The problem was that FixedUpdate sometimes can run multiple times in one frame, causing "GetButtonDown" being registered also multiple times, hence the double jump height. So, one solution would be to check input in Update method and in FixedUpdate only do the jumping itself: public float jumpHeight = 10;
bool hasJumped;
Rigidbody rb;
void Awake()
{
rb = GetComponent<Rigidbody>();
}
void Update()
{
if(Input.GetButtonDown("Jump"))
{
hasJumped = true;
}
}
void FixedUpdate()
{
if(hasJumped)
{
rb.AddRelativeForce(Vector3.up * jumpHeight, ForceMode.VelocityChange);
hasJumped = false;
}
}
Here is the problem though: Update get's called after FixedUpdate, so your jump can sometimes start 1 frame later. It's not a big problem, but if you want it to be perfect - you need to check if FixedUpdate was called on that frame with Time.frameCount, so the Jump will occur exactly once and exactly in the frame when button was pressed, like this:
public class jump : MonoBehaviour {
Rigidbody rb;
int jumpFrame;
public float jumpHeight = 10;
void Awake()
{
rb = GetComponent<Rigidbody>();
}
void FixedUpdate()
{
if(Input.GetButtonDown("Jump"))
{
Jump();
}
}
void Jump()
{
if(Time.frameCount != jumpFrame)
{
jumpFrame = Time.frameCount;
rb.AddRelativeForce(Vector3.up * jumpHeight, ForceMode.VelocityChange);
}
}
}
Answer by theterrificjd · Dec 25, 2017 at 09:20 AM
You said you needed it, I just wanted to clarify (for a jump solution, anyway). Because AddRelativeForce is in relative position to the object, my understanding is that typically, unless you're tinkering with variable "world up" directions, AddForce(Vector3.up) is what you want, because otherwise its getting the transform objects up rotation (which can be a problem if you spin at all).
Beyond that, if you just want a raw Velocity change, you can just do:
rb.velocity = rb.velocity + (transform.up * jumpHeight);
This is relative to the transform object, but if you don't need it relative, you can use Vector3.up instead of transform.up.
Or experiment with ForceMode.Impulse instead (my personal preference, as I like the impulse curve).
Thanks, for helping, i got the solution, had to post it as another answer, though
Your answer
Follow this Question
Related Questions
Calculate velocity to set to reach a target point on a plane considering the drag. 0 Answers
Accelerate a rigidbody towards max speed 2 Answers
Rigidbody character controller can't walk on stairs 0 Answers
The player doesn't jump to the left with the W key pressed 0 Answers
SImply yet tricky question about RELATIVE VELOCITIES... 1 Answer