Godot Multiplayer Tutorial - Interpolation | Godot Dedicated Server #12

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments

Doesn't using OS.get_system_time_msecs() on both sides implicitly assume that the system time is the same on the client as it is on the server? Of course it's true / close enough in your demo setup, but what if a client sets their system time 5 minutes into the future / past?

👍︎︎ 6 👤︎︎ u/G-Brain 📅︎︎ Dec 07 2020 🗫︎ replies
Captions
in this godot tutorial i'll teach you how you can interpolate between various world states so that you can make the movement of various entities on the map look super smooth without increasing the bandwidth requirements of the network let's get started in the last tutorial we made sure that we can see other players on the map move around we did so at 20 frames per second as that is the tick time of our server that made that the movement looks a little bit choppy a little bit laggy and that's of course undesirable now we don't want to increase the number of ticks of the server because that will basically reduce the performance and reduce the amount of concurrently connected players that the server will be able to handle so we are going to be interpolating now what's interpolating to explain to you how interpolation works i'm going to be using a visual we got the server that is sending out the world state 20 times per second or every 50 milliseconds and let's say as an example that our client needs to render the frame at 10 seconds 285 milliseconds there's a problem here because the client only knows where the players were in the game at 10 25 the packet which contains the world state at 10 30 still has to be received by the client it doesn't know that yet and a packet may not even arrive it's a packet after all can get lost on the internet so this is what's creating that choppiness that lagginess because we're updating that position only 20 times per second as we don't really know where the player is going so interpolation how is it going to help us with interpolation we're going to say that we're going to render not at 10 285 but we'll tell the client to render the world 100 milliseconds in the past now you might be going whoa whoa whoa that means it's not real time anymore and yeah you're absolutely right but surprise surprise this is industry standard name any mmo rpg name battle royales like fortnite or pub g they all use this mechanic to buffer world states into an interpolation function so what's actually going to help us well now we got two time stems 10 15 and 10 20 which have a world state with a position a vector 2. now we can say at 10 185 well we know where the player was and we know where the player is going to go and we know how much time the player is going to take to get from point a to point b so we can pretty much calculate with this data on literally every single millisecond between those two world states where the player most likely has been and if we make a small deviation in this calculation this will automatically get corrected as we receive the next world state so with this method we are able to very accurately at any given time that a frame needs to be rendered calculate where that player needs to go where we need to place it without actually having the server take more ticks or or tick faster and without having to send any extra data over the network thereby we are reducing the bandwidth requirements for our players and you know everybody loves that so now all we gotta do is put this in the code put it in our game good news for you in this tutorial we'll only be working in one of our four projects for a change so let's get started the code i got selected right now is the code from the previous tutorial number 11. and we have to unravel this code a little bit put it into two different functions the update will say right here and the physics process i've renamed this old function to update world state alt and we'll be retiring all this code but we will be making sure that we check and i'll show you where the code has been replaced or updated or upgraded so the first thing we can retire is these two lines on the top because those two lines have been copied 101 into the update world state right here the thing we do differently now is that we are going to append the world say we received from the server into the world state buffer the world saved buffer is nothing more than an empty array defined on the top now before we go into these other lines of code let me first show you what we're actually going to do with that buffer to make sure we can run all the calculations in a convenient way let's say so first thing we need to do is we have to determine the render time that's the time of the frame that we're going to render that's going to be a timestamp and that's one of the three crucial timestamps to make this interpolation work we do this by getting the operating system's time in milliseconds minus the interpolation offset the interpolation offset is a constant on the top which i have defined as 100 milliseconds i would say start out development with 100 and based on the geography that your player base is in you might want to reduce or increase it now next thing is we have to make sure that the world state buffer has the correct build up what i mean by that i've wrote written uh well it's not code actually it's just a more an indication visualization we want the buffer to not you know keep on appending and collecting more world states as a player has a single gameplay session because if we collect world states 20 a second for three hours long then that array is going to be super slow super big just gonna eat up memory basically so we want to make sure that we clean that buffer up constantly and ideally the build up of that buffer is going to be the same every single time so we can make easy references in the calculations so what we want is we want index number zero the first index to be the most recent past world state so it's going to be in the past but the most recent one in the past and then the index number one or the second index is going to be the nearest future world state and then after that we can keep on collecting any other world states that might be more that might be less that doesn't really matter so to get that what we first do is we check if the world state has at least two world order the buffer has at least two world states if it doesn't have two world states none of this code is gonna work we're gonna throw errors we don't want errors that's not good for our game so we check if we have at least two world states else calculations won't work then while the world state buffer size is more than two so it's going to be three four or five we're gonna check if the render time timestamp is bigger than the timestamp of index number one in the world state buffer now what does that mean we're checking if the render time has become bigger than the nearest future world state because if that's the case it's not in the future anymore and we can move the nearest future world state into the most recent world state and we can move any other future world state that has a time stamp that's even further in the future to the nearest future world state the way we do that is we simply remove index number zero so that would not be the most recent past but the the time stem before that or the will stay before that we don't use it anymore it's useless to us at this point we simply remove it and as we remove index number zero everything is going to shift one position up and we're again ending up with the right circumstances now what's important is that you use a wow function here because it might be the case under some circumstances that you're going to have several of these packets that need to be deleted in order to get the right world state that especially happens at startup of the game and if you don't use a while loop here most likely you're going to go out of sync and then things are going to look really weird so make sure you use while not if then what we need to do is we need to determine based on the timestamp of recent past and recent future and render time three time stamps how much time has passed in expressing a percentage from state in the past to state in the future because if we're very close to the future state we want the position to be closer to the future state however if the most recent past world state is just in the past two milliseconds in the past we means that we need to render the position of the player very close to that state to do that we're going to be lurping that position but in order to learn we need to have the factor between two positions that it needs to lurk in between now if you want to look that up you better be looking up lerp as in function you can go search help you can go lerp and you can look up more information on how a function exactly works so we're going to need that interpolation factor we get that by taking the time that has elapsed from the previous world state the one in the past to the current render time and we divide that by the difference in time between both world states that we are lurping in between as we have that we can now start looping over every single player in our world state and start determining its position based on the render time instead of based on the world state time to do that and that's basically where we're going to cross over into our old code so that's basically this function or this line of code right here we still have two deletions out of our world state here in the previous code previously we were erasing the timestamp of the world state well we have already used the timestamp of the world state here to determine the interpolation factor but we haven't used it yet for any extrapolation and the timestamp that might be very handy in the future so i don't want to be deleting it anymore so we're not going to delete that and also the deletion of the player id well i've opted for a different solution which i think is a little bit cleaner that is right here first we check if that player is equal to the t of timestamp in which case we continue we don't delete it we simply skip over it we continue to the next player in the for loop we do the same if the player is its own network id we continue to the next player in the for loop and another check we have to do if we have to make sure that the player that we're going over is available in both world states if the player just logged in it might be the case that that player is not available in the old world state and if the player just disconnected the player might not be available in the future world state so we have to make sure that that player is available in both world states otherwise the code would run into an error now once we have all that we you can see we start going into very similar code right here now instead of simply saying move player and then with the position of the world state we are first determining the new position by lerping this is where that lerp comes in so we're going to take the position out of the world state in the past at index zero the will the position out of the world state at in the future at index number one in the buffer and we are pushing that interpolation factor which is going to be the same because we're basically got two will stay so that factor is always the same that's why we define the factor one time on the top and then we use it for every single player we're lurping over now as we have the new position now we take exactly the same function as before but instead of pushing the position from the world state we're pushing a new position that we have determined by lurping between two world states one in the past one in the future then here the code is pretty much exactly the same only difference is that instead of taking the player position out of will say player p we now have to take it out of the world state that is stored in the buffer and that's why it looks a little bit different so with that we are pretty much interpolating the positions and our movement should look much smoother and let me quickly delete this line of code and i think we can give it a test so i got my two clients i've got two different usernames and password already set in so i'm gonna log in on this side i'm gonna log in on this slide and now we can move around here and as you can see the player movement is super smooth we don't have any of that choppiness anymore that we have in the previous tutorial and of course this one works exactly the same that was it for today guys hope you like it if you did smash that like button hit subscribe don't forget that little bell icon to make sure that you don't miss out on our next episode in the next episode we're going to be taking a look at extrapolation extrapolation is pretty much the same process but then what if we don't have a future state what if the packets simply weren't reliable enough and we don't have a future packet how can we still make sure that that movement stays smooth also in the next episode i'll address an issue that this code has created because now we are rendering 100 milliseconds in the past the moment a player disconnects the interpolation function basically spawns that player straight in again so currently you can't disconnect without actually having the player disappear from the play field that's an issue that i'll address together with extrapolation in the next tutorial hope to see you then until then keep on gaming keep on coding see you later guys
Info
Channel: Game Development Center
Views: 4,807
Rating: undefined out of 5
Keywords: Godot Syncing Players, Godot Multiplayer Syncing Players, Godot Multiplayer Players Move, Godot Multiplayer Moving Players, Godot Multiplayer Tutorial, Godot Multiplayer Syncing, Godot Multiplayer Interpolation, Godot Interpolation, Godot Network, Godot Networking, Godot Dedicated Server, Godot Multiplayer Server, How to make a multiplayer game, Godot MMO, Godot Beginner Tutorial, Godot 2d Tutorial, Godot Tutorial, Godot
Id: w2p0ugw3afs
Channel Id: undefined
Length: 13min 19sec (799 seconds)
Published: Sun Dec 06 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.