[DEMO] Basic Network Physics Sync

So I have built a very basic network physics sync library, along with a test server/client.
Looking for feedback on it. I am using a slightly different approach than I have used in the past.

I have some thread safe issues to address, but for the purpose of the demo it is fine.

Thoughts?

2 Likes

Why not use SimEthereal which will do reliable UDP?

Edit: just in case SimEthereal is “brand new information”, here is the overview: Overview · Simsilica/SimEthereal Wiki · GitHub

I just wanted to build one, just for the sake of seeing how to do so. I have built other implementations in the past, but they were much more integrated with my applications. I just wanted something standalone and lightweight.

I personally have never used SimEthereal, but it is on my list of things to do to learn it.

Fair enough… you asked for thoughts…

So, as to your approach, the problem with a straight-up UDP approach that does not worry about contiguous frames, reliability, etc. is that packets will drop randomly. So one object may be seen to move while another staggers, etc…

Each of your per-object messages is already pretty huge. 7 floats + a string + serializer overhead for the object hierarchy. Going to be at least 60+ bytes for the average message, once per object, once per frame. The per-message UDP overhead is also going to be 28 bytes… so every object is taking up 88+ bytes of network x times per second depending on your frame rate.

…Strings are also not a great way to identify objects.

Given that your message sizes will vary, it makes it even more likely that some specific object will get messages and some others won’t.

For reference, SimEthereal uses a semi-reliable UDP transport where the client and the server keep track of a “known good state”. Only the deltas from the known good state are sent and they are packed tightly into single messages if possible. (It can send updates for about 80 active objects in one 1400 byte message or several hundred objects if they aren’t moving). It breaks up frames automatically if there are more objects moving than can fit in one standard MTU message size (we’d prefer to break up the messages ourselves versus making the IP transport do it).

In addition, it keeps track of which objects are within local view range and only sends updates for those objects.

A fully working non-ES (non-EntitySystem) demo can be found here:

An ES version can be found here:

They are basically space ship games without the game. You can login and fly space ships around and see your friends and their spaceships. (“Spaceship!”)

2 Likes

I will have to look into using that. I was torn between assigning my own IDs, or using some existing identification that JME has internally. I decided to use JME’s spatial’s names, but yes, strings are a terrible way to address objects.

I will take a look at the demos. Perhaps I will adapt this and learn SimEthereal at the same time :wink:

Thank you for the feedback!

1 Like

Awesome, thanks for the very good explanation.
I have also started writing my own network library just for seeing how network gaming works.
I however soon realized that it is surely a skill that not every have.

I wanted to test and prove if jME’s multiplayer capability will work on Android as a client and I did get it to work if anyone else is interested.

I will definitely look into your SimEthereal library.

1 Like

I have made some improvements.
Client will ignore out-of-order packets.
I have added interpolation to the client.
Server batches object updates into fewer messages.

My only issue now is that for some reason my interpolation for my rotation causes the cube to jump in its rotation. Still do not know why… Position interpolation seems to work great.

SimEthereal delegates to SimMath for this which has frame transition classes which handle position/rotation interpolation.

Those classes also use some thread tricks to support lock-free multithreaded access as long as only one thread writes… many threads can read.

1 Like

Ah, I did not know about the slerp function! That fixed my issue, thank you!

The python implementation of bullet has the ability to save and load the state of the simulation. I was not able to find, but probably looking in the wrong place, for if we have that functionally implemented in bullet-native.

I was thinking of being able to do a save state every 100ms, then being able to do lag compensation checks against it.

Is this even possible with our current integration with bullet?

1 Like

We don’t have that functionality, not in jme3-jbullet, nor in jme3-bullet, nor in Minie.

I downloaded your PhysicsSync project and made sure it also works with Minie v1.3.0for33.

I’m trying to envision how a lag compensation check might be performed, if PhysicsSpace load/save were implemented. By comparing the saved states byte-for-byte?

1 Like

No, valve has an approach where they load the saved state into a new physics environment and execute what ever action the client performed in the past to get the results.

An example is in a first person shooter if the client is lagged 125ms, then use the save state from 100ms ago, to check what the user shot.

1 Like

Note: SimEthereal is collecting all of the state that a player can see every frame in a compact form… and keeps it around for a while waiting for ACKs. I don’t know if it’s possible/easy to intercept this state and keep it for your own purposes… but it’s essentially exactly what you need (assuming only position is required) and already filtered down to only what the user can see.

Edit: I guess my point is that if you do all of the other things necessary for proper network synching then you already have this information.

1 Like

In JME, all collision objects implement the Savable interface, so I imagine it wouldn’t be difficult to implement Savable for an entire PhysicsSpace … mostly a matter of looping over all collision objects in the space.

1 Like