[SOLVED] Is it possible to have a strict async with update and draw?

Solved!

TimeSpan updateCount = new TimeSpan(0);
long refreshRate;
long updateRate;
TimeSpan updateInterval ;
TimeSpan refreshInterval;


private void updateTiming()
{
    updateRate  = 2400; //How many times within a second should update loop.
    refreshRate =  144;

    updateInterval  = new TimeSpan((long)10000000 / updateRate );
    refreshInterval = new TimeSpan((long)10000000 / refreshRate);
}

public void update(GameTime gameTime)
{
    while (updateCount <= refreshInterval)
    {
        deltaTime = (float)gameTime.ElapsedGameTime.TotalSeconds;

        inputMngr.poll        ();

        stateMngr.updateStates();

        inputMngr.clearPoll   ();

        updateCount = updateCount + updateInterval;
    }

    updateCount = new TimeSpan(0);
}

public void draw(SpriteBatch spriteBatch, BasicEffect basicEffect)
{
    stateMngr.drawState                                   ();
    display  .draw     (spriteBatch, basicEffect, deltaTime);
}

Half Solved:

    this.TargetElapsedTime = new TimeSpan(16667);
    this.IsFixedTimeStep   = true;
    //Allows me to get 600 times a second perfectly. But I need vsync to be forced on.

Using:

this.TargetElapsedTime = TimeSpan.FromMilliseconds(1.6666666666666666667d);
//Is apparently some soddy broken shit.

Update 2
If I try to use gameTime.ElapsedGameTime.TotalMiliseconds >= 1.66666667f in a conditional for my update. The update and draw rate becomes very unstable. Even though the game runs fine with fixed time step set to true, with a target elapsed time set to 1000 times a second… This occurs with TotalSeconds as well, with values of 0.01f…

Update
So I noticed something about monogame’s TargetElapsedTime…
If you set your speed to 400 times a second , it will instead run at 500 times a second.
Trying to do 600 times a second gives 500…, 1000. Essentially once you hit around 300updates per second monogame becomes less accurate in providing the exact number of updates you wanted with target elapsed time.

Essentially what I’ve seen from monogame so far is that I’m restricted to 0- 333(With some innaccuracies), 500, and 1000 updates per second.

Original Post:
I’m working on a platform fighter using Monogame. Due to how technical its going to be I need to tie all the mechanics to a strict update interval.

I went on and decided I wanted to have a polling rate of 480 calls per second for update, where input, physics, and logic are all called in the same update call. This leaves 8 frames of higher accuracy per 60th of a second that should remove any possibility of jank happening in-game; what hitbox collided first, grabs, positioning, etc. Allows for less of a luck factor in a player getting “frame perfect” (1/60th second traditionally) inputs. (See port priority in melee for example). There is also a strict polling rate that is consistent which should help with the netcode later on. This also adds support for monitor refresh rates up to 480hz(if such a thing even gets to exist…).

So far the only way I see to enforce this is using fixed time step.

I however want to allow for draw to be strictly independent from update. Like taking a shot with a camera, I just want it to take a snap shot of what it see when it Monogame decides it can see whats going on in update. In case Vsync is used I would naturally want it to to restrict it self to the refresh buffer.

Using fixed time step though seems to disable Vsync, and turning it off fails to keep it at a steady rate.

Am I forced to to use conditionals to the update in check by using an elapsed time formula, or is there a way I haven’t found to do what I desire without having to go that route.

Edit: Grammar.

If you set IsFixedTimeStep to false the game will simply call update and draw repeatedly as fast as it can. You then are responsible for your own timing and targetElapsedTime in this case has no effect at all.

If you set IsFixedTimeStep to true.

Then targetElapsedTime applys to both update and draw.

Then to set the target elapsed time for both a update and draw you pass.

Using seconds you pass
= ( 1d / desiredFramesPerSecond );

Using milliseconds to set FPS you pass
= ( 1000d / desiredFramesPerSecond );

( 1.6666 ) milliseconds directly is 600 fps. ( e.g. 600 updates And draws )

Note:
A frame is not really a update or a draw alone, its both. Its really draws per second provided IsRunningSlowly does not evaluate to true. Which implicity includes a prior update. To say a target time is a target frame time which is a implied update and then a draw.

The only exception to that is in the case that you explicitly set PresentInterval to a non default value.

I don’t really see why you would want to update more then draw but you could simply add a counter to your updates and short circit out of your entire draw by only drawing after so many updates .

Draw …
{
if( updateCount == 10)
{
// clear the device draw the stuff clear the counter
}
base.Draw
}

Update …
{
// do update stuff
updateCount ++;
base.Update;
}

1 Like

So after just settling with my solution in my halfed solved response in the original post, I decided to work on various other parts of my game like input management, an on screen text input ui, among other things.

This still bugged me so I decided to look at the above post again on how you said to properly do update and draw.

I was finally able to come to a great solution that works with enormous disparity in update and draw intervals.

Code snippet for the main handler of the engine I’m doing:

TimeSpan updateCount = new TimeSpan(0);
long refreshRate;
long updateRate;
TimeSpan updateInterval ;
TimeSpan refreshInterval;


private void updateTiming()
{
    updateRate  = 2400; //How many times within a second should update loop.
    refreshRate =  144;

    updateInterval  = new TimeSpan((long)10000000 / updateRate );
    refreshInterval = new TimeSpan((long)10000000 / refreshRate);
}

public void update(GameTime gameTime)
{
    while (updateCount <= refreshInterval)
    {
        deltaTime = (float)gameTime.ElapsedGameTime.TotalSeconds;

        inputMngr.poll        ();

        stateMngr.updateStates();

        inputMngr.clearPoll   ();

        updateCount = updateCount + updateInterval;
    }

    updateCount = new TimeSpan(0);
}

public void draw(SpriteBatch spriteBatch, BasicEffect basicEffect)
{
    stateMngr.drawState                                   ();
    display  .draw     (spriteBatch, basicEffect, deltaTime);
}

With this, I can have VSync off and use fixed time step. Right now my update rate and refresh rate is hardcoded as in the example, but these will be user adjustable later on. I’m using a high update rate to stress test, it and it worked phenomenally.

The only real downside to this method is that your mechanics timing must be able to adjust to different update intervals so everything still occurs at the same rate in real time and is not sped up or slowed down. This can be easily done using some scaling function to make your timing values for mechanics a constant across different update intervals. Something similar to resolution and aspect ratio independent rendering of the game.

Thanks for the advice!