In the game I’m currently working on, I’m starting with something very simple, a character automatically running forward (x-axis), and the player just controls the jumps. I’ve accomplished this with scripts similar to the following
Running (On Update() function)
if (isAlive)
{
rigidBody2D.velocity = new Vector2(moveSpeed, rigidBody2D.velocity.y);
}
Jumping (Using OnJump of the new InputSystem)
if (value.isPressed && isOnTheGround && isAlive)
{
rigidBody2D.velocity += new Vector2(0f, jumpForce);
}
Hence, as you see, I’m using velocity for the movement, and for each frame update changing this velocity.
I’ve configured the gravity and moveSpeed settings so that the jumps feel good, for a starting speed. Although, on the next phase of the game, I want to increase the speed of the horizontal movement, but by just increasing the ‘moveSpeed’ variable, the jump feel alters completely, it makes a much bigger jump (higher X-axis distance, longer air time, …). I want it to have the same fast impulsive jump up and down.
My question is if there is a better way to do this, instead of just tweaking the gravity + moveSpeed until it feels right for a given speed? Is it even correct to change the gravity mid game? From a physics perspective it would make sense that the gravity remains the same throughout the game, if it’s the same ‘environment’.
That was exactly what I was looking to accomplish, regardless of the speed to have the same snappiness to the jump. The idea of the game is to have a continuously running object/player that needs to jump to avoid obstacles, and increase the speed as they progress through the platform. So it was important to keep the same ‘feel’ for the jump, the difficulty just increases due to the speed.
The only change I’ve made to your script is to have the calculation of the gravity magnitude on the FixedUpdate(), instead of just the start, because I will be changing the speed multiplier mid game.
Just a couple of questions:
For this specific case, we are using FixedUpdate() instead of Update() because we are changing the velocity right? We are changing the physics of the object.
My jump logic is on a different method, that will not be called from the FixedUpdate, because it’s the OnJump() function to listen the Input System events. Does that make a difference? Because for the jump we are changing the velocity, and not on the FixedUpdate().
Physics runs by default during the “FixedUpdate”. Doing work like setting the velocity per-frame during “Update” is pointless because you might do that several times before the simulation runs. Of course, you can run the simulation per-frame if you like and do away with FixedUpdate but that’s the reason.
You always have to read input per-frame because that’s how it comes in. You just don’t want to be doing work on physics there because of what I said above.
All in all, it just comes down to understanding the difference of Update and FixedUpdate. If you use the default FixedUpdate which happens at 50Hz but your framerate is 200Hz then you get 4 updates for every single FixedUpdate.
Totally makes sense. It would be a nightmare to design an endless runner level that feels good at ALL speeds if the jump distance or height was changing.
This is great, the only tweak I would suggest is:
read the OnJump and set a boolean in your update
check that boolean in FixedUpdate() to do the jump (and clear it when you jump)
Not sure in your case it would make any discernible difference but physics is always best done in FixedUpdate().
Two good discussions on Update() vs FixedUpdate() timing:
Although @Kurt-Dekker , I noticed that for higher speeds I wasn’t getting the expected results. I tested it also on your code sample, and the same happens. Your code works perfectly for lower speeds, but at a certain point, with higher speeds the height start decreasing, as you see here:
I think I figured out the issue, with such higher speeds the default rate of the FixedUpdate() calls is not enough, with higher speeds we loose too much precision. If I decrease this timestamp between calls from 0.02 to 0.001 for example, the result if exactly what we’re looking for
I think you are correct. Anything that is sampled at discrete intervals can exhibit issues like this as the sample length nears the total event length.