- Home /
Framerate Independence for 2D Platformer
Greetings,
This is my first post about my 2D platformer character jumping higher when the frame rate drops.
Here are some code snippets as I am unsure where else I need to do a Time.deltaTime multiplier. I would appreciate any feedback on this.
void UpdateMovementOffsets()
{
isMovementBlocked = false;
// Check to see if we can move horizontally in this direction
if(playerBlockedLeft && currentDirection == Vector3.left) isMovementBlocked = true;
if(playerBlockedRight && currentDirection == Vector3.right) isMovementBlocked = true;
// Make sure we are able to move in the horizontal direction we are attempting to move by checking if we are blocked
if(!isMovementBlocked)
horizontalMovementOffset = currentDirection * horizontalSpeed * Time.deltaTime;
else
horizontalMovementOffset = currentDirection * 0.0f; //no movement
// Calculate Verital movement offset for player for this frame
if(!playerIsOnTheGround)
verticalMovementOffset = new Vector3(0.0f, verticalSpeed, 0.0f) * Time.deltaTime;
else
verticalMovementOffset = new Vector3(0.0f, 0.0f, 0.0f);
}
Then the two functions I actually calculate the vertical and horizontal offsets.
void UpdateHorizontalMovement()
{
targetSpeed = Mathf.Min(Mathf.Abs(horizontalMoveValue), 1.0f); //returns the smallest of two or more values.
targetSpeed *= walkSpeed;
horizontalSpeed = Mathf.Lerp(horizontalSpeed, targetSpeed, speedSmoothing); //interpolates between a and b by t. t is clamped between 0
}
...and for vertical movement
void UpdateVerticalMovement()
{
// Adjust for gravity
if(!playerIsOnTheGround)
verticalSpeed -= gravity;
// Make sure Player does not fall too fast
if(verticalSpeed < -maxFallSpeed)
verticalSpeed = -maxFallSpeed;
// Handle a player jump action
if(applyJumpVelocity)
{
playerIsOnTheGround = false;
verticalSpeed = Mathf.Sqrt(50 * jumpHeight * gravity);
AudioSource.PlayClipAtPoint(jumpSound, myTransform.position, 0.75f); //last value is for volume
}
}
what are you using as the type of character controller?
RigidBody, Is$$anonymous$$inematicRigidBody, CharacterController?
I am not using the built in Unity Character Controller. I am moving the character like this in my Update function:
myTransform.Translate(horizontal$$anonymous$$ovementOffset + vertical$$anonymous$$ovementOffset);
I am applying Time.deltaTime to both the horizontal$$anonymous$$ovementOffset and the vertical$$anonymous$$ovementOffset calculation yet my character still jumps higher when the frame rate drops.
I think I am just missing another application of Time.deltaTime to all of my variables to make them "movement units" ins$$anonymous$$d of just unrelated values.
For example: gravity might really need to be gravityUnits = gravity Time.deltaTime; and jumpHeight might need to be jumpHeightUnits = jumpHeight Time.deltaTime;
Something like that...any suggestions?
Answer by nsejosh · Nov 20, 2012 at 04:51 PM
I'm pretty sure your character jumps higher with low framerate because you're subtracting gravity from the speed in a frame rate independent fashion- if you think about it, at a high frame rate, you're speed is going to decrease much faster than at a low frame rate. you need to multiple gravity by Time.deltaTime as well ( and then scale it appropriately so that at your target framerate it's still the number you expect ). In other words, you acceleration needs to be based on deltaTime as well as your Velocity. Good luck!
Answer by Xevoius · Nov 20, 2012 at 08:29 PM
I think I get what you are saying and it probably should read " you're NOT subtracting gravity from the speed in a frame rate independent fashion".
I will try and apply the Time.deltaTime to all the values I have specified for calculations (gravity, maxFallSpeed, jumpHeight, walkSpeed and speedSmoothing) as well as scaling factors and try and dial the movement in again to work like it should.
Hi! well it depends how you're interpreting "frame rate independent" :) What I mean is, you're not taking the frame rate into account, yet still doing it every frame, which is the problem.
Also, my answer is assu$$anonymous$$g you're using Update to do all this- if you're using FixedUpdate then frame rate independence should be handled for you, and deltaTime is just the fixed update time regardless of framerate, but given the problem you're having and the way the other stuff is written I'm assu$$anonymous$$g you're using Update.
Answer by Xevoius · Nov 25, 2012 at 07:13 PM
Yes, I am using Update(). I have solved the horizontal framerate independent movement but the jumping has been stubborn.
Answer by Xevoius · Nov 25, 2012 at 07:12 PM
Ok, I solved the problem through trial and error. My 2D platformer is now be framerate independent. Thanks for the feedback. I will post my solution in a few days.
i'd really like to know how you fixed the problem cause I am having the same issue, can you help out?
First I figure out the player's horizontal speed like this
void UpdateHorizontal$$anonymous$$ovement()
{
// $$anonymous$$ake all horizontal movement calculations
targetSpeed = $$anonymous$$athf.$$anonymous$$in($$anonymous$$athf.Abs(horizontal$$anonymous$$oveValue), 1.0f); //returns the smallest of two or more values.
targetSpeed *= walkSpeed;
horizontalSpeed = $$anonymous$$athf.Lerp(horizontalSpeed, targetSpeed, speedSmoothing); //interpolates between a and b by t. t is clamped between 0
}
Then I figure out vertical movement something like this
void UpdateVertical$$anonymous$$ovement()
{
// Handle a player jump action
if(applyJumpVelocity)
{
playerIsOnTheGround = false;
verticalSpeed = jumpHeight;
}
// Adjust for gravity
if(!playerIsOnTheGround)
verticalSpeed -= gravity * (Time.deltaTime * Game$$anonymous$$anager.deltaTimeScalingFactor); //apply framerate independent gravity per second adjustment
// $$anonymous$$ake sure Player does not fall too fast
if(verticalSpeed < -maxFallSpeed)
verticalSpeed = -maxFallSpeed;
}
Then I do this at the bottom of my player's Update()where movementOffset is a Vector3 whose X and Y coordinates have already been adjusted by my functions above.
void Update()
{
...
movementOffset *= (Time.deltaTime * Game$$anonymous$$anager.deltaTimeScalingFactor);
myTransform.position += new Vector3(movementOffset.x, movementOffset.y, 0.0f);
}
I hope this helps you out.
Your answer
Follow this Question
Related Questions
Framerate Dependent Mesh Deformation 1 Answer
Accurate Frames Per Second Count 5 Answers
How do I find the frames per second of my game? 6 Answers
How to change framerate for Android? 1 Answer
Parenting Weapon to Empty = Framerate drops to 2fps 2 Answers