Time correction when changing a value based on Time passed.

Started by
7 comments, last by DiegoSLTS 9 years, 5 months ago

Alright, in our game whenever the player jumps we calculate when he should start falling based on how long he has been jumping for. This causes issues when the game is running at the fastest setting, since the deltaTime is added more frequently. I tried normalizing the vector returned by muliplying by deltaTime, but that just made the jump return a very tiny movement vector everytime. So, how could I go about normalizing the deltaTime?

Here's our code:


private Vector3 OnPress()
{
	jumpTimer = 0;
	jumpVelocity = new Vector3(0f, 11.5f, 0f);
	return jumpVelocity;
}

private Vector3 Rising()
{
	jumpTimer += Time.deltaTime;
	jumpVelocity = (gravity * jumpTimer) + jumpVelocity;
	return jumpVelocity;
}

private Vector3 Dropping()
{
	jumpTimer += Time.deltaTime;
	jumpVelocity = gravity * jumpTimer;
	return jumpVelocity;
}

private Vector3 Landing()
{
	jumpVelocity = Vector3.zero;
	jumpTimer = 0f;
	return jumpVelocity;
}

I believe the issue is within Dropping and Rising. Thanks.

Advertisement

Is that Unity? Do the physic updates inside the FixedUpdate function to prevent different behaviour with different frame rates.

If it isn't Unity, implement a fixedUpdate method. Do something like this in your game loop:


float accumulatedDeltaTime = 0f;

while(!quitting) {
  // stuff
  UpdateEverything(deltaTime);
  accumulatedDeltaTime += deltaTime;
  while(accumulatedDeltaTime >= FIXED_UPDATE_TIME) {
    FixedUpdateEverything(FIXED_UPDATE_TIME);
    accumulatedDeltaTime -= FIXED_UPDATE_TIME;
  }
  // more stuff
}

If deltaTime is small, you'll skip the fixedUpdates of small values and delay it a few frames. If the deltaTime is big, you'll do more than one fixed update in one frame.

Rembember to not accumulate time in float/double variables.


implement a fixedUpdate method.

Thumbs up.

I would change that loop slightly, if desired for smoother display:

// interpolate positions, rotations, etc. between the previous update and the current one.

// objects maintain previous update data to support interpolation

// display is actually one "frame" behind

InterpolateFixedUpdateObjects( deltaTime, FIXED_UPDATE_TIME ); // provide intermediate graphics display parameters

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

Yeah, it's Unity for now. Personally, I'm trying to minimize our business logic's dependency on Unity, so I can switch the game to Monogame without too much difficulty. I know FixedUpdate() would make the code respond more accurately with variables on machine speed, I'm just worried that that would make the game feel less responsive.

Yeah, it's Unity for now. Personally, I'm trying to minimize our business logic's dependency on Unity, so I can switch the game to Monogame without too much difficulty. I know FixedUpdate() would make the code respond more accurately with variables on machine speed, I'm just worried that that would make the game feel less responsive.

Try it, do not waste time looking for a workaround of a problem that you don't have. The FixedUpdate method exists to solve the exact problem you have, if you try that approach and it doesn't work well within your game start looking for alternatives.

Are you planning to migrate to Monogame? Why not just do it with Monogame instead? Or is it something that you think would be nice to be able to do if for some unknown reason you decide to do it in an undetermined time on the future that may not happen? This sounds bad, you usually do not change the engine of the game during development.

Or maybe your Unity game is a prototype before the real game using Monogame? If it's a prototype, you're not supposed to keep the code, it should be the fastest thing you can do to make something work and test it.

Also, I don't know how's the workflow with Monogame, but Unity uses a lot of engine stuff, wouldn't switching to Monogame require you to replace even the GameObject class?

Replacing the GameObject class wouldn't be too bad, as I'm developing with Test Driven Development, and Unity isn't the best environment for TDD, so I'm creating many little classes that get wrapped by GameObjects. The hardest part would be making the animations from the artists animate correctly. Basically, we're using Unity since not everyone on the team knows how to program.

Alright, in our game whenever the player jumps we calculate when he should start falling based on how long he has been jumping for. This causes issues when the game is running at the fastest setting, since the deltaTime is added more frequently. I tried normalizing the vector returned by muliplying by deltaTime, but that just made the jump return a very tiny movement vector everytime. So, how could I go about normalizing the deltaTime?

Here's our code:

private Vector3 OnPress()
{
	jumpTimer = 0;
	jumpVelocity = new Vector3(0f, 11.5f, 0f);
	return jumpVelocity;
}

private Vector3 Rising()
{
	jumpTimer += Time.deltaTime;
	jumpVelocity = (gravity * jumpTimer) + jumpVelocity;
	return jumpVelocity;
}

private Vector3 Dropping()
{
	jumpTimer += Time.deltaTime;
	jumpVelocity = gravity * jumpTimer;
	return jumpVelocity;
}

private Vector3 Landing()
{
	jumpVelocity = Vector3.zero;
	jumpTimer = 0f;
	return jumpVelocity;
}
I believe the issue is within Dropping and Rising. Thanks.

Rewriting your current code, it's pretty much this:
onJump:
	acceleration = 0;
	velocity = (0, 11.5, 0);
rising:
	acceleration += deltaTime * gravity;
	velocity += acceleration; //n.b. deltaTime not used here!!!
dropping:
	acceleration += deltaTime * gravity;
	velocity = acceleration; //n.b. = used, not += ???
onLand:
	velocity = (0,0,0);
	acceleration = 0;
...which shows that your equations of motion are wrong. Velocity is updated without any respect to delta time, which is why it will vary greatly with framerate.


Also, I'm not sure why rising and dropping need different update functions. You should be able to just use something like this:
onJump:
	acceleration = 0;
	velocity = (0, 11.5, 0);
rising:
dropping:
	acceleration += deltaTime * gravity;
	velocity += deltaTime * acceleration;
onLand:
	velocity = (0,0,0);
	acceleration = 0;
Or an alternate version:
onJump:
        onGround = false;
	impulse = (0, 11.5, 0);
onLand:
	onGround = true;
	impulse = (0, -velocity.y, 0);
update:
        if( !onGround )
		acceleration += gravity * deltaTime ;
	velocity += acceleration * deltaTime + impulse;
	impulse = (0,0,0);
^^Both of those versions update velocity using deltaTime, so they should be more stable. However, they will still give slightly different results with different frame-rates, due to them being an approximate numerical integration of the motion curve.


To solve that, you can either use a fixed timestep (as mentioned by everyone above), or you can use a version that is based on absolute time values, instead of delta time values, which makes it perfectly deterministic and always works the same regardless of framerate:
onJump:
        onGround = false;
	initialJumpHeight = height;
	initialJumpVelocity = 11.5;
	timeAtJump = timeNow;
onLand:
	onGround = true;
update:
	if( !onGround ) {
		timeSinceJump = timeNow - timeAtJump;
		//motion under constant acceleration: o' = o + ut + att/2
		//(o'=new pos, o=initial pos, u=intiial velocity, t=time since initial conditions, a=acceleration)
		height = initialJumpHeight + initialJumpVelocity*timeSinceJump + 0.5*gravity*timeSinceJump*timeSinceJump;
	}
	return height;

Replacing the GameObject class wouldn't be too bad, as I'm developing with Test Driven Development, and Unity isn't the best environment for TDD, so I'm creating many little classes that get wrapped by GameObjects. The hardest part would be making the animations from the artists animate correctly. Basically, we're using Unity since not everyone on the team knows how to program.

But do you have any reason to change to Monogame? It sounds like you just don't like Unity. If Unity is not a good environment for TDD you shouldn't be using it.

I guess that the more you do with Unity, the harder it will be to change for the whole team. And as long as you want to use Unity but not use Unity's stuff, the development will be harder and slower too.

Those people that can't code won't be able to work if you change to Monogame, you'll be adding a problem to the project. What do those people do? Are they artists, sound and level designers? Unity is great to test those aspects directly in the game, but how will they work after the change?

Anyway, all this looks kind of offtopic, but I think it's a bad idea to change to Monogame if you don't have a good reason, and even worse if you avoid using things and make development harder without some advantage.

This topic is closed to new replies.

Advertisement