Synchronizing BetterCharacterControl across a network

Hello all, I’m currently in the process of writing a networked FPS. I’ve got the very basics set up, ie. walking around and client-server syncing with an authorative server, position interpolation and lag compensation. I’ve read the Source articles etc… I’m using physics on both the client and server, and the client performs the actions immediately as well as sending the inputs to the server. My problem is how to adjust the client’s position when it is invariably slightly different to what the server says it should be. Both sides use the BetterCharacterControl. I originally used warp() on the client side, but this can introduce problems like moving the player through a wall, and also made the client jittery.

Adjusting the BetterCharacterControl by setting the walkDirection seemed ideal, since I theoretically can set it to the difference between the client and server positions (or a fraction of it). However, this is not an exact science (that I can see). For example, if the difference between the client and server is Vector3f(1, 0, 0), just adding this to the walkDirection doesn’t properly correct the clients position as it often overshoots or something. I think this is a due to walkDirection implementing its own acceleration, among other things.

So, in a nutshell can anyone please help and tell me the best way to sync a client’s BetterCharacterControl position against a server’s BetterCharacterControl? Thanks a lot in advance.

1 Like

How are you networking these together? Spidermonkey? I presume you are not using an entity-component system? What topology are you using? Because UDP should be hammering your character with positions…

1 Like

Translating the question for you in case its illuminating:
“How do I use a visual-specific object not designed for networking to synchronize my game object’s position?”

You are going to have a bad time.

1 Like

Yeah i get that but its more of a where do i even start. The client represents the servers state. I feel like i say that so often it becomes a mantra. I guess thats the beginning.

1 Like

I’m using Spidermonkey to send data between client and server, and I’m using my own simple entity system. I’m not sure I understand the other replies? Are you saying that I should be going about it a different way, e.g. not using physics on the client side?

1 Like

Your client should only request directions at velocities, or some kind of variant, and your server should respond with the result constantly. Thats generally how it works. So it means that everything is server side (im gonna regret that). And your client is the representation of what your server dictates. Therefore physics, collisions, players and everything else are server side. The mathematical description of your vision. And the client turns that into art, with queries to the server. Can i move here? No. Theres a wall. Or yes its clear.

If you dont, it means i am the master and your server is the slave. I dictate the laws of physics. Of collision. Of every cheat you hate.

And theres the benefit of it making more sense, or course, when you go through the motions :slight_smile:

1 Like

That sounds like pretty much what I’ve already got. It’s an authoritative server that sends out updates every 100ms or so. However, I’m trying to implement client-side prediction by running the same code (including physics) on the client, and then correcting the client when there’s a discrepancy, but that’s where my problem is.

1 Like

Then you must understand that there is no such thing as synchronization, but instead interpollation of given data. There should be no client aide authority as you have.

1 Like

I think we must be at cross-purposes, and maybe synchronization is the wrong word. My setup has an authoritative server, but the client attempts to predict what position it should be in, by interpolating the correct position based on the data it has received from the server. However, my problem is moving the BetterCharacterControl to the correct position when the client is informed that its prediction was wrong.

1 Like

Your client requests to move in some vector fashion. The server gives you a location back. And a direction i guess. You dont need physics client side at all in this particuar part of your problem. Your client knows what to do because the server is constantly telling it where to be. It wont fall if you update it slowly, as i expect it would if the client was dictating its location. Like yours is…

You arent doing what you think you are doing. The client must never dictate its state.

1 Like

Doing it that way would introduce too much lag, as the client wouldn’t move until it has sent the player’s input to the server, and the server has sent back the new position.

https://developer.valvesoftware.com/wiki/Source_Multiplayer_Networking#Input_prediction

1 Like

The server is telling your player one thing, and the client side physics is doing it as well. You already did the physics server side. Now you keep a history of it and interpollate. Its coming thick and fast, too, so it wont be far behind. Id say as far behind as your ping.

1 Like

And i must state that “interpollate” is a very broad term here. This is guru territory.

1 Like

But that comes back to my original problem - how do I then move the BetterCharacterControl once I’ve “interpolated” the correct position?

1 Like

You dont. Because you have already done everything server side and now you are visualizing the results.

1 Like

Are you saying I should have a ~200ms delay between the player pressing “forwards” and the view actually changing?

Im wondering how you came to that figure.

This game is intended to be played on the internet. Ping times can vary a lot, and also UDP isn’t 100% reliable, so a missed packet will obviously cause even more delay. I’ve just googled “overwatch ping times” and it varies from 50 - 250, and their equipment is obviously going to be a lot better than mine.

Basically, “input prediction” is a thing that needs to be implemented in any serious game.

I never said otherwise. I just said dont do it twice. Your client is a dumb terminal. Get rid of anything that tries otherwise. I.e. bettercharactercontrol. Make a player object based on values given by the server. Thats your network version of bettercharactercontrol. All phyicsed, collisioned and everything elsed up by the server already and ready to display as visual data…

Given that characters usually accelerate, often the 200 ms lag time is not hugely noticeable. You do 100% have to give the player full real time control of their view direction but the movement can have quite a bit of lag before it’s a problem. Effectively, half the lag gets gobbled up as an initial jump in acceleration.

As to the other, I wouldn’t use BetterCharacterControl at all. It makes no sense on the server and it kind of makes no sense on the client. You need a simplified physics model on the client even if you want to do prediction and that simplified physics model has to have no momentum AT ALL and incorporate interpolation right at the very foundation.

This is what I mean. If you build your game on top of stuff that is meant for single player then you will struggle constantly with it. warp() is not a solution because you will still have accumulated momentum and stuff. Because BetterCharacterControl is a real physics object and not a kinematic one, it’s just bad and wasteful to warp it 20x a second or more.