properly updating dynamics world (step)

Software: Away3D 4.x

Tom.de, Newbie
Posted: 14 June 2012 06:01 PM   Total Posts: 30

Hey everyone,

this is probably something quite simple but I can’t seem to get it right.

I need to get my physics simulation properly frame-rate independent.
On some systems it will run with nearly 60 frames per second while on others it will run on quite a bit below 30.
I need the simulation speed to be persistent however.

Here is what I am doing at the moment:

private var _nFixedTimeStep Number 1.0 60;
private var 
_iSubTimeSteps int 1;
private var 
_last_step Number 0;

public function 
update(dtMilliseconds:Number):void
{
 
if ((getTimer() - _last_step) > _nFixedTimeStep)
 
{
  
// calculate _iSubTimeSteps for framerates below _nFixedTimeStep
  
_iSubTimeSteps = (dtMilliseconds 1000) / _nFixedTimeStep;
  if (
_iSubTimeSteps 1)
   
_iSubTimeSteps 1;
  
// step and remember last step
  
awpDynamicsWorld.step(dtMilliseconds/1000.0_iSubTimeSteps_nFixedTimeStep);
  
_last_step getTimer();
 
}

As you can see I calculate the number of subtimesteps for lower frame-rates. Originally I thought just setting this to a higher number will take care of it automatically but then, at high frame-rates, it will run way too fast.
Therefore I calculate them for lower frame-rates. This seems to work fine but I do get jerky behaviour which comes from when my frame-rate is just below the 60 I presume? Not pretty. Am I over-engineering this?

edit: I should add that the frame-rate is not stable, it varies quite a bit during gameplay. Unfortunately I have no influence on that. Is there a way to compensate that? Having a stable simulation speed at various frame-rates even when it changes mid game?

   

Tom.de, Newbie
Posted: 15 June 2012 10:00 AM   Total Posts: 30   [ # 1 ]

After much reading and testing I’ve come to these possible solutions:

awpDynamicsWorld.step(dtMilliseconds 1000.01000.01); 

This seems frame-rate independent but projectiles feel “jittery”.

awpDynamicsWorld.step(dtMilliseconds/1000.00); 

The documentation says not to do this one, but it works perfectly. At all frame-rates I get the same behaviour and it feels properly frame-rate independent.

   

Tom.de, Newbie
Posted: 15 June 2012 11:25 AM   Total Posts: 30   [ # 2 ]

Now both of the two solutions I’ve found above come with a new problem.
I am now occasionally missing out on my collision event.

collisionCallbackOn is set to true and below is how I add the listener.
m_Rigidbody.addEventListener(AWPEvent.COLLISION_ADDED, onCollision);

It works perfectly when I update my dynamics world like so:

awpDynamicsWorld.step(dtMilliseconds / 1000.0, 1);

however, this is NOT frame-rate independent. If I use one of the solutions form the previous post, it will occasionally miss events. (The collision still happens correctly, just that the event is never fired?)

Any ideas what that could be? I am really starting to be at a loss here…

   

Etherlord, Newbie
Posted: 16 June 2012 11:30 AM   Total Posts: 6   [ # 3 ]

I am a beginner as well, but indeed it looks over-engineered.

1. Once You use dtMiliseconds parameter, the other time You compute time with getTimer(); I think You should either remove the dtMiliseconds, or use getTimer on higher level, leaving the specific job of computing timeStep to the function only.

2. Shouldn’t

_iSubTimeSteps = (dtMilliseconds 1000) / _nFixedTimeStep

be replaced with

_iSubTimeSteps Math.ceil dtMilliseconds/1000 _nFixedTimeStep ); 

... ?

3. I don’t know how the function uses time left from first parameter, that is smaller then _nFixedTimeStep. Maybe it is better to just set all parameters by hand, that is:

private var _nFixedTimeStep Number 1.0 60.0;
private var 
_last_step Number getTimer();

public function 
update():void
{
   
var currentTime:Number getTimer();
   var 
secondsPassed:Number = (currentTime _last_step) / 1000.0;
   
_last_step currentTime;
   
   var 
steps:int 1;
   var 
subStepTime:Number secondsPassed;
   if ( 
timePassed _nFixedTimeStep {
      steps 
Math.ceil secondsPassed_nFixedTimeStep );
      
subStepTimesecondsPassed steps;
   
}
   
   awpDynamicsWorld
.step secondsPassedstepssubStepTime );
 
}
   

John Brookes, Moderator
Posted: 16 June 2012 04:10 PM   Total Posts: 732   [ # 4 ]

maxSubsSteps is the maximum amount of internal ticks you want the physics to do.

If you have a scene that gets a lot of collisons going off and you calc the substep like above your phyiscs can grind to a halt (spiral of death). You use this value to stop that from happening.

But also realise that the physics will slow down the rendering if the amount of substeps and or amount of stuff happening is too high.
So
Reduce the number of collisions or buy everyone a new Pc smile


physics.step(dt,0);
This is just a single step of time. So no substepping.
Thats the reason you think its frame independant. Thing is its not that acurrate. Your saying from start to finsh do one calc. Things can tunnel and miss events.

Anyhoo thats how I see it.

   
   

X

Away3D Forum

Member Login

Username

Password

Remember_me



X