Jump to content
  • Advertisement
Sign in to follow this  
graveyard filla

Unity problem with time based movement

This topic is 4963 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

hi, i have a problem with time based movement, which is kind of related to this thread. anyway, im working on a 2d online RPG. the problem is this - what if a player's computer chokes up, and the time_passed variable is something big, which sends them flying through a wall or completely off the map? how do we prevent this? locking the frame-rate is not an option, as this is an online game and if a person ever had a frame-rate lower then the locked version, he would be completely out of sync. thanks for any help.

Share this post


Link to post
Share on other sites
Advertisement
To the specific problem you're mentioning, you could do a trace from his previous position, to where he would be after the time delta passed. If any obstacle is found during the trace, handle the collision at that point.

Share this post


Link to post
Share on other sites
Or if time_passed is to big divide update function into a few parts.


void DummyUpdate( float time_passed ) {
while ( time_passed > max_time_passed ) {
TrueUpdate( max_time_passed );
time_passed -= max_time_passed;
}
TrueUpdate( time_passed );
}

Share this post


Link to post
Share on other sites
actually some one had a time based question, you helped them, i tried it and reported back to the same thread with the same problem, i agree with DELVIN but im not sure how easy this will be to do depending on the API your using

Share this post


Link to post
Share on other sites
1) use volicity as a factor in determining your collisions

-or-

2) Don't let players update themselves like that. It should only be an issue if the *server* hiccups. Now if player (A) has a hiccup and goes through a wall, on his next update he says "Move Player Left 2.5 units". Server says "2.5 units left. Got it. That puts you on 156x, 790y, correct?". Client says "Uh... well, it's kinda funny you should mention that. See, uh...". Server sends an update packet. "You are now at 156x, 790y... or else!". Client says "156x, 790y. Got it." and snaps back.

Share this post


Link to post
Share on other sites
Generally speaking there are two common ways that this is dealt with.

One is a fixed update rate:


ULONG t; //Global or somesuch

//Inside game loop:
t += time_beween_frames;
while( t > update_time ) //eg 10 milliseconds
{
UpdateGame();
t -= update_time;
}

//This is an EXAMPE
//There are probably better way to go about doing this



The other is to use swept collision tests. Both methods have been mentioned in the previous thread linked in the original post.

Jackson Allan

Share this post


Link to post
Share on other sites
hey everyone,

@leavoia

could you maybe explain a little bit by what you mean about using velocity as a part of the collision detection? also, i may consider just having the server correct the client like you suggested. the positions already re-sync each time a client moves anyway. i already need to put a check in to verify coordinates for security reasons.. if the coords the player sent me are not close to the coords the server has, then the server would send that client the position the server has and the client would set his position to this.

however, the one problem is that i still need to do this on the server anyway. so if i write the code to do it, i might as well put it on the client as well. if i didnt do it on the server, i would be totally screwed if for some reason the server choked. one thing is, i may decide to go with a less elegant method like locking the frame rate while still doing time based movement on the server. then i could get away with doing no extra work really [smile].

@jack

im having a problem understanding the logic to this fixed update thing. so the UpdateGame() function should be the main loop basically? i dunno, just a little confused.

thanks again.

anyway, im going crazy not being able to get this to work. here is the code i have :

bool Collision_Mediator::Attempt_To_Move(Character *character,const Uint32 ms_passed, float xVel, float yVel)
{
//we will do steps in 10 millisecond increments
const int STEPTIME = 5;

//save our starting position
const float old_x = character->X_Pos();
const float old_y = character->Y_Pos();

Uint32 timestep = STEPTIME;//ms_passed > STEPTIME ? STEPTIME : ms_passed;

bool hit_obstacle = false;

//while we haven't done a time step as big as our DT
while(timestep < ms_passed)
{
//how many seconds have passed since this timestep?
float secs_passed = (float)(timestep) * 0.001f;

//set our position to what it would be at, at this time
character->Set_X(character->X_Pos() + (xVel * secs_passed));
character->Set_Y(character->Y_Pos() + (yVel * secs_passed));

////if we are colliding with anything in this spot, we can stop testing for collisions
////this function should set our new X/Y position after the collision reaction
if(Run_Collision_Check(character))
{
//bail out!
cout << " detected collision while doing the step by step jump"<<endl;
cout << ms_passed << " <--- DT "<<endl;
cout << timestep <<" <--- current timestep"<<endl;

hit_obstacle = true;
break;
}

//advance another 10 MS (if possible)
if ((secs_passed - timestep) > STEPTIME)
timestep += STEPTIME;
else
timestep += ms_passed - timestep;

//re-set to our original position so our movement doesn't accumulate
character->Set_X(old_x);
character->Set_Y(old_y);

}//end while(timestep < dt)


//if we didn't hit an obstacle, that means our position got re-set, so lets move our full step
//since now we know its legal!!!
if(!hit_obstacle)
{
float secs_passed = (float)ms_passed * 0.001f;
character->Set_X(old_x + (xVel * secs_passed));
character->Set_Y(old_y + (yVel * secs_passed));
}

//if we hit an obstacle, return true
return hit_obstacle;

}







and Run_Collision_Check looks like this:

bool Collision_Mediator::Run_Collision_Check(Character *character)
{
//this function loops through all characters and does collision detection / reaction with each character with the parameter character
//now do collision for this character against all other characters!
for(std::list<Character*>::iterator it = Character::characters_in_world.begin();
it != Character::characters_in_world.end(); ++it)
{
//if this is ourself, continue..
if(*it == character)
continue;

//if this character is not on the same map, continue
if((*it)->Get_Map() != character->Get_Map())
continue;

//if we collide, do the collision reaction and then return true!
if(Is_Colliding(*it,character))
{
Collision_Reaction(*it,character);
return true;
}
}

return false;
}







now, each frame, inside Character::Update(), i do something like this:

Collision_Mediator::Attempt_To_Move(this,time.time_passed,x_vel,y_vel);

however, this isn't working properly. when testing it out with 2 clients and the server running, the collision was not consistant on both machines. if 2 characters were close and one moved, on one client he might collide and on another he might not. i just can't figure out what im doing wrong. i also use this same function, Attempt_To_Move() when i get a packet about another client moving somewhere. i get a packet that says something like "hey im standing here at X,Y and i clicked here at X,Y at time T". then i put that client in that position, calculate how much time has passed since this happened using the time stamp, and then "jump" that far to make up for the lost time, so that the clients are in sync with each other. the problem is that the "jump" might jump me over another a character or a wall. so i use this function again, here, like this:

Attempt_To_Move(this,time_passed,x_vel,y_vel);

where time_passed was how long ago the packet was created. anyway, i have no clue why this is not working. you can read more about the problem in this thread. thanks again.

ps, yes, i know that whole collision mediator thing is ugly and the functions might be better as a member of the Character class, but this was quick and dirty and is "obvious" if you know what i mean.

[Edited by - graveyard filla on December 15, 2004 2:31:40 AM]

Share this post


Link to post
Share on other sites
what i mean is that you need to use swept volumes for your collision tests. The volume is the collision geometry (box, i imagine) and the "sweep" is the Velocity * Time. This way you can see if two objects collide at somewhere in the near future and move them up or repel them as needed. It makes sure you don't miss anything. You can either use a straight-up swept geometry test or a Seperation Axis algorithm as many others would recomend. If you are only using boxes, you might go with a straight test. If you are using any other kind of geometry, you'll want to use the algorithm.

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.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!