- Home /
Problem with jumping and frames per second
I'm making a very simple 2d platforming game in 3d graphic style with unity. My main character is a character controller which moves in the direction of the Vector3 called moveDirection. I used the function Move from the character controller class to make him move.
To accomplish the jumping, I made a simple code
if(Input.GetButtonDown("Jump") && character.isGrounded){moveDirection.y = jumpSpeed;}
being jumpSpeed a float number, and character, the refference to the character controller. So the thing works perfectly, it jumps as I wanted it to do, but when I compiled the game I found a problem. The character jumped less (significantly less, about a 10%) than in the test. I thought it would be a problem of frames per second, and I multpiplied the jumpSpeed by Time.deltaTime, but that hasn't worked, because I'm giving an absolute number, not increasing it, so what it does now is jumping in a random value because of Time.deltaTime.
How can I fix this? I can change the jump speed but then it wouldn't work in another computer with another FPS rate right? The other movement parts are done with Time.deltaTime and work well, but they're not absolute numbers, they are an increase (or decrease) of the current value, so it works. I can't do this with jumping because the result is not what I was expecting, so I need help on making this work.
Thank you.
Answer by aldonaletto · Aug 02, 2011 at 01:48 AM
The problem is the way you're applying gravity: gravity must increase the down velocity proportionally to time. That's why moveDirection.y is decreased by gravity * Time.deltaTime - it makes the gravity effect frame rate independent. Since you're dividing gravity by 25, it will do the same effect at 25 fps, but will vary at other frame rates. Restore the Time.deltaTime factor like below:
function Update() { ... // gravity * Time.deltaTime makes gravity fps independent moveDirection.y -= gravity * Time.deltaTime; monkey.Move(moveDirection*Time.deltaTime); }
I solved it but I didn't know why, so thank you very much for explaining it to me.
So in this approach, are you disabling gravity on the players rigidbody2d and just applying your own gravity to the player within the update loop?
No, this script is intended for the 3D physics CharacterController: the gravity must be simulated because this component isn't affected by forces (gravity included). There's no CharacterController in the 2D physics engine - regular Rigidbody2D components are used ins$$anonymous$$d. It would be hard to create a true "CharacterController2D", but there are several videos $$anonymous$$ching how to simulate it in the youtube and in Unity's tutorials.
Answer by niX_BB · Aug 01, 2011 at 11:34 AM
If you want a consistent jump height I would suggest moving your jump logic to fixed update and calculating the jump speed with Mathf.Sqrt(jumpHeight * -Physics.gravity.y)
Don't forget that GetButtonDown won't work reliably in FixedUpdate so keep the input check in Update but apply the jump in FixedUpdate
This doesn't seem to work with my game :S. But now that I think about it, i multiply the whole moveDirection vector by Time.deltaTime so the jump is also multiplied by time.deltaTime, now I don't know what could it be. I'm also having other kind of problems with other things that don't happen to me during the editor test.
Could you post some code, it would be easier to spot your problem.
I posted in another answer, i didn't know how to post code as a comment.
I've fixed it, but i didn't know why did it work like that. I had
movedirection.y -= gravity, and I changed it by gravity*Time.deltaTime, but I was already multiplying the whole Vector by Time.deltaTime, why didn't it work then?
Anyway, the problem is fixed Thank you very much.
Glad you got it working, don't forget flag the question as answered.
Answer by SilverTabby · Aug 01, 2011 at 11:18 AM
You can try using FixedUpdate in conjunction with Time.fixedDeltaTime or Time.captureFramerate.
Answer by Setzer22 · Aug 01, 2011 at 07:36 PM
I'll post some more code (in JavaScript). by the way, monkey is a refference to the character controller:
function Update () {
//Debug.Log(attacking);
Animations();
Checkings();
Controls();
moveDirection.x = -Input.GetAxis("Horizontal")* speed;
moveDirection.y -= (gravity)/25;
if(moveDirection.y<-1 && monkey.isGrounded){moveDirection.y = -1;}
//I made this above to avoid the gravity affecting the character when he's grounded It //didn't work if i set it at 0.
monkey.Move(moveDirection*Time.deltaTime);
}
function Controls (){
if(Input.GetButtonDown("Jump") && monkey.isGrounded){JumpState = true;}
}
function FixedUpdate () {
if (JumpState == true){moveDirection.y = Mathf.Sqrt(jumpSpeed * -Physics.gravity.y); JumpState = false;}
}