I am using Raknet as networking engine and trying to implement FPS movement. So far made 2 attempts:
1. Send packet when player holds key to move, when he releases, and constantly update direction;
2. Constantly keep sending new position.
In both ways movement was very choppy, player was teleporting randomly, or even fully unsynched (like in 1st attempt).
So my question is, how can I achieve smooth movement for FPS? Similar to ones Counter Strike, Call of Duty, Section 8, Borderlands and other games have, I never seen any choppy movement, random teleports or etc in them.
Thank you in advance.
[C++, Raknet, DX9] FPS Movement?
The quite elaborate Source Engine Networking description should serve as a good starting point. Feel free to disregard everything that is not directly related to movement for now.
In short, the way it works in Source is that the client side lags 50 ms behind the server, and interpolates (rather than extrapolates) each player's position between the last two updates. Updates are sent at a predefined interval (I believe it's 20Hz in Source?), and the client buffers each update until a new one arrives, finally moving the player object through the interpolation process mentioned above.
EDIT: This comes with two primary benefits:
1. The game won't be choppy, because players can be moved in a very smooth manner during interpolation.
2. The client won't ever fail to correctly "predict" the position of an entity (simply because it doesn't do any prediction).
I've implemented this approach in one of my games, and found that it worked very well.
In short, the way it works in Source is that the client side lags 50 ms behind the server, and interpolates (rather than extrapolates) each player's position between the last two updates. Updates are sent at a predefined interval (I believe it's 20Hz in Source?), and the client buffers each update until a new one arrives, finally moving the player object through the interpolation process mentioned above.
EDIT: This comes with two primary benefits:
1. The game won't be choppy, because players can be moved in a very smooth manner during interpolation.
2. The client won't ever fail to correctly "predict" the position of an entity (simply because it doesn't do any prediction).
I've implemented this approach in one of my games, and found that it worked very well.
Both ways shouldnt have been choppy? I used to send updates of position and rotation for every update and I had like 115ms ping. You need to make sure it is sent in time steps though. Sending data every frame will lead to lag. But if you send updates every 30ms you should be fine.
Your other way with keypresses is what I am doing now, but I haven't tested it live on the internet, but obviously it is a better solution.
So I don't know what your problem might be.
Your other way with keypresses is what I am doing now, but I haven't tested it live on the internet, but obviously it is a better solution.
So I don't know what your problem might be.
Quote:Original post by Ripiz
1. Send packet when player holds key to move, when he releases, and constantly update direction;
It takes a finite amount of time to send packets. Think of somewhere around 150ms which means you're getting latency of nearly ten frames (at 60 fps).
Added to this time there is seemingly random jitter so some UDP packets can arrive before others, or not at a constant rate, or some will be dropped.
If you're using guaranteed delivery with or without in order delivery then there is extra time taken to receive packets and make sure they are presented to you in order.
This can mean double or more latency for your packets if packets are dropped and then resent. Of course, with movement updates it is generally a good idea to not send them with guaranteed delivery since with movement updates they are usually being constantly sent anyway so just wait for the next one to come along.
Imagine that you are randomly pressing the movement key to simulate the latency due to the network, this is what your code is seeing. So sending key presses and running those key presses on the client leads to the choppy movement you're seeing.
Quote:2. Constantly keep sending new position.
This was probably an improvement over sending key presses, but it still won't be smooth because you need to smooth out the random jitter of packets from the network layer. You can do this in several different ways.
1) A concept of unified network time helps synchronise the clients. You can then receive packet updates using update deltas and extrapolate the position. When a packet is received it is immediately processed. But you'll need to apply extra filtering/smoothing to that position. This kind of works OK. But it is not the smoothest update option. It is useful if you want to see the results of a packet arriving in the next rendered frame.
2) You can use the update delta idea but on each client have a latency of some constant value applied to all movement. This lets you buffer all movement packets received and internally they can be sorted in order and processed. Since you are using the extra latency to compensate for the random jitter coming from the network packets your movement on screen also appears smoother.
This lagged/buffered update functionality is similar to the implementation offered by the SetLagged function I wrote for this class. http://www.replicanet.com/assets/docs/Main/html/classRNReplicaNet_1_1DataBlock__Predict__Float.html#c9de7bd8b7400c41608a476ab06751f2
This class basically handles the job of receiving updates from the network and also creating updates for clients to receive and specialises in updating floating point values. It has all sort of other tricks for lowering the bandwidth of object updates that are "far away" from a client.
Another thing I think you might find to be useful is the ability to debug what your network layer is doing for your object updates. There is nothing worse than not having enough information to debug problems. Debug information like what updates it is sending, to where, how big they are and the reason why updates were sent. A tool to collect this debug information and display it in a format more easily read is also useful. This is why I wrote the RNVisualDebugger tool which can collect information from a network session as it is running. You can then view a graph of the network bandwidth used, highlight spikes in the bandwidth and drill down into the data to see exactly what object updates were being sent during that particular time. Since the rules for object updates are defined by you the programmer you can then decide to tweak the update update parameters to reduce network bandwidth for those problematic updates.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement