Jump to content
  • Advertisement
Sign in to follow this  
JonBonazza

deltaTime issues

This topic is 2613 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

First of all, I should note that I am developing this engine for the android OS, so memory, CPU speed, and GPU speed are all limited. I am also using Java, however on most relatively newer android devices--provided they are running at least android 2.2--Java is JIT compiled rather than interpreted. i am also making use of the JNI and native code whenever I see fit.

At any rate, I am having some issues implementing a deltaTime variable.
I have this class"


public class Time
{
public static long timeFrameStarted = 0; // system time at start of frame
public static long timeOfStart; // system time of the start of the scene
public static float deltaTime = 0; //time it took to complete last frame
public static long frameCount = 0; // Number of rendered frames
}


and my update function called each from looks like so:


public void onDrawFrame(GL10 gl)
{
Time.timeFrameStarted = System.currentTimeMillis();
++Time.frameCount;
Log.e("IMPACT", "" + Time.deltaTime);
// TODO Auto-generated method stub
go.transform.position.x += 100 * Time.deltaTime;
go.update();
Time.deltaTime = (float)((System.currentTimeMillis() - Time.timeFrameStarted)/1000.f);
}


go is my GameObject. Everything else should be self explanatory.

At any rate, this code does work, however as the game object is moving across the screen, it will move smoothly, then jerk forward, move smoothly again, then jerk forward again, and so on.

I am not sure if it has something to do with my implementation of deltaTime or if I simply need to optimize my openGL code inside of my draw methods.

Here is a video of the issue in case it helps:

Share this post


Link to post
Share on other sites
Advertisement
Well, after thinking about it some more, I realized that this should be expected from the code. I am moving my object by a different value every frame.
So I suppose the correct question should be, what should I do instead?

I am aiming for frame-rate independence, by the way.

Share this post


Link to post
Share on other sites

Well, after thinking about it some more, I realized that this should be expected from the code. I am moving my object by a different value every frame.
So I suppose the correct question should be, what should I do instead?

I am aiming for frame-rate independence, by the way.


You're scaling your movement by how much time the last [font="CourierNew, monospace"]onDrawFrame[/font][font="Arial"] call [/font][font="Arial"]took. I assume you want to scale by how much time has elapsed since the last movement?[/font]
[font="Arial"] [/font]
[font="Arial"]Also experiment with the resolution of [/font][color=#1C2837][size=2][color=#660066][font=CourierNew, monospace]System[/font][color=#666600][font=CourierNew, monospace].[/font][color=#000000][font=CourierNew, monospace]currentTimeMillis[/font][color=#666600][font="CourierNew, monospace"]()[/font][font="Arial"] on the android. If it's low enough, you'll get wonky results.[/font]

Share this post


Link to post
Share on other sites

[quote name='jonbonazza' timestamp='1319077850' post='4874533']
Well, after thinking about it some more, I realized that this should be expected from the code. I am moving my object by a different value every frame.
So I suppose the correct question should be, what should I do instead?

I am aiming for frame-rate independence, by the way.


You're scaling your movement by how much time the last [font="CourierNew, monospace"]onDrawFrame[/font][font="Arial"] call [/font][font="Arial"]took. I assume you want to scale by how much time has elapsed since the last movement?[/font]

[font="Arial"]Also experiment with the resolution of [/font][color="#1C2837"][color="#660066"][font="CourierNew, monospace"]System[/font][color="#666600"][font="CourierNew, monospace"].[/font][color="#000000"][font="CourierNew, monospace"]currentTimeMillis[/font][color="#666600"][font="CourierNew, monospace"]()[/font][font="Arial"] on the android. If it's low enough, you'll get wonky results.[/font]
[/quote]

Thanks for the reply.

I have sinced switched over to System.nanoTime() which seems to be a higher resolution.
At any rate, I have found this article:
http://gafferongames.com/game-physics/fix-your-timestep/

and after refactoring me code, I have this:



private final float tick = 0.02f;
private float tickTime = 0;
private float currentTime = 0;


public void onDrawFrame(GL10 gl)
{
float newTime = System.nanoTime()/1000000000.0f;
Time.deltaTime = newTime - currentTime;

currentTime = newTime;

tickTime += Time.deltaTime;

while(tickTime > tick)
{
tickTime -= tick;

Log.e("IMPACT", "" + Time.deltaTime);
// TODO Auto-generated method stub
go.transform.position.x += 30 * Time.deltaTime;
go.update();

}


++Time.frameCount;

}


However, although better, things are still pretty jumpy.
I tried playing with the value of tick, but nothing seems to work. :/

Share this post


Link to post
Share on other sites
When you use a fixed timestep, you should be using a constant delta time value. Take another look at the article.

Share this post


Link to post
Share on other sites
I think that you should put in line:

[color=#1C2837][size=2][color=#000000]go[color=#666600].[color=#000000]transform[color=#666600].[color=#000000]position[color=#666600].[color=#000000]x [color=#666600]+=[color=#000000] [color=#006666]30[color=#000000] [color=#666600]*[color=#000000] [color=#660066]Time[color=#666600].[color=#000000]deltaTime[color=#666600];

tick instead of Time.deltaTime.

So it would be:
[size=2][color=#000000]go[color=#666600].[color=#000000]transform[color=#666600].[color=#000000]position[color=#666600].[color=#000000]x [color=#666600]+=[color=#000000] [color=#006666]30[color=#000000] [color=#666600]*[color=#000000] [color="#660066"]tick[color=#666600];

Also, make sure that tickTime is global, i.e. whenever a call to
[color=#1C2837][size=2][color=#000088]public[color=#000000] [color=#000088]void[color=#000000] onDrawFrame[color=#666600]([color=#000000]GL10 gl[color=#666600])[color=#000000] is made tickTime should not be zero, but hold the remaining time from last call.

Share this post


Link to post
Share on other sites
You're mixing truly frame-rate independent code (what you're trying to do) with fixed-framerate code (from the article).

I'd go back to the original way you were doing it, but store the nanoseconds, not nanoseconds/1000000000, and divide only the delta. You may lose some precision otherwise.

void OnDrawFrame()
{
float newTime = System.nanoTime();
Time.deltaTime = newTime - Time.currentTime;
Time.currentTime = newTime;

go.transform.position.x += 100 * (Time.deltaTime/1000000000.0f);
go.update();
}


Share this post


Link to post
Share on other sites

You're mixing truly frame-rate independent code (what you're trying to do) with fixed-framerate code (from the article).

I'd go back to the original way you were doing it, but store the nanoseconds, not nanoseconds/1000000000, and divide only the delta. You may lose some precision otherwise.

void OnDrawFrame()
{
float newTime = System.nanoTime();
Time.deltaTime = newTime - Time.currentTime;
Time.currentTime = newTime;

go.transform.position.x += 100 * (Time.deltaTime/1000000000.0f);
go.update();
}


So, am I safe in assuming that the above method should be used for rendering, while the fixed framerate code (from the article) should be used for physics calculations?

Share this post


Link to post
Share on other sites
Well, after doing what you siad, everything seems to be working correctly. In fact, even if I divide by 1 billion immediatley instead of doing it when multiplying by deltaTime, it still works. Apparently I forgot to test System.nanoTime() wiht my initial implementation.

Here is my final code in case anyone can use it.

Time class


public class Time
{
public static float deltaTime = 0; //time it took to complete last frame
public static long frameCount = 0; // Number of rendered frames
public static float fixedTime = 0; //The time that the last fixed update was called
public static float fixedDeltaTime = 0.1f; //The interval, in seconds, at which fixed updates are performed
public static float maxDeltaTime = 0.25f; //The maximum time that a frame can take for fixed updates
}


frame update:


private float currentTime = 0;
private float frameTime = 0;
private float accumulator = 0.0f;


public void onDrawFrame(GL10 gl)
{
float newTime = System.nanoTime() / 1000000000.0f;
Time.deltaTime = frameTime = newTime - currentTime;

if(frameTime > Time.maxDeltaTime)
frameTime = Time.maxDeltaTime;

currentTime = newTime;

accumulator += frameTime;

while(accumulator > Time.fixedDeltaTime)
{
//Perform Fixed Updates here
accumulator -= Time.fixedDeltaTime;
}

//Perform all non-physics-related updates here

++Time.frameCount;

}


Feel free to make suggestions on ways to improve it.

Share this post


Link to post
Share on other sites

Well, after doing what you siad, everything seems to be working correctly. In fact, even if I divide by 1 billion immediatley instead of doing it when multiplying by deltaTime, it still works. Apparently I forgot to test System.nanoTime() wiht my initial implementation.



Well, that makes sense. I figured the nanosecond implementation would've worked, but suggested a way to get better precision. BTW, you WILL get better precision if you stall the divide until after computing the delta in nanoseconds, but it really shouldn't matter much.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!