- Home /
High-velocity network synchronisation
I am making a large-scale space exploration game, where players can possibly travel at absolute high speeds (between 100 and 10,000 m/s) - but at the same time, fairly or very low velocities relative to each other.
I am using Floating Origin (and retaining a decimal
Vector3
of the difference between the local floating origin, and the absolute/server origin) with a threshold of either 64 or 256 metres, to avoid precision issues with the large distances involved, and I already have the synchronisation of these origins solved. Each game unit is one metre.
However, issues related to velocity (and because of that, position) network synchronisation start happening slightly around 150 m/s, and turn inacceptable around 200-250 m/s.
The following is an excerpt from the OnSerializeNetworkView code that handles synchronisation. Note that I am not only factoring in velocity based on latency, but acceleration as well - and yet I still see discrepancies of about 5 metres almost every network packet regarding position at speeds of about 200-250 m/s.
Vector3m
is a custom decimal
Vector3
.
if (!stream.isWriting) {
stream.Serialize(ref position);
stream.Serialize(ref velocity);
stream.Serialize(ref acceleration);
stream.Serialize(ref rotation);
stream.Serialize(ref angularVelocity);
stream.Serialize(ref originXX);
// ... snip ...
stream.Serialize(ref originZW);
origin = Vector3m.decode(
originXX, originXY, originXZ, originXW,
originYX, originYY, originYZ, originYW,
originZX, originZY, originZZ, originZW
);
rigidbody.velocity = velocity;
rigidbody.velocity += acceleration * (float)(Network.time - info.timestamp);
rigidbody.position = (origin + new Vector3m(position) - Player.self.origin).vector3;
rigidbody.position += rigidbody.velocity * (float)(Network.time - info.timestamp);
rigidbody.rotation = rotation;
rigidbody.angularVelocity = angularVelocity;
}
Increasing (or decreasing) the network sendrate does not make the issue better or worse.
The nature of the issue is such that increasingly often (and by 250 m/s, almost every packet) the position delta (network extrapolated position minus current rigidbody.position) is off by a few metres.
At 150 m/s, it is off by about 3-4 metres, whereas at 250 m/s, it is off by at least 5-6 metres. At higher velocities, the issue becomes even more pronounced. I have tried interpolation, but the odd thing is that the packets I receive give vary from being correct to being 5-6 metres off. This means interpolation still forces the character to jump back and forth.
If there was a mistake in my prediction, I would assume the position to constantly move one way, instead of jumping back and forth.
I have also tried floating origin velocity, where the actual velocity never exceeds, say, 16 m/s. This does not improve or worsen the situation, however.
Are there any gotchas I should be aware of related to this, or any mistakes in or aprovements to my approach, or is there a different approach entirely I should take to achieve better synchronisation at high speeds?
I'm pondering your question but would point out that setting a rigidbody position outside of FixedUpdate and specifically adjusting the velocity is likely to cause all sorts of problems. You can add forces from anywhere, but specifically moving it is a generally bad plan.
Interesting. I never knew setting rigidbody position or velocity outside of FixedUpdate was problematic.
How does the standard NetworkView do it when observing a rigidbody, then?
I will try moving the position/velocity setting to the FixedUpdate function now, though, and see if that does anything.
Thank you for your input :)
Worth a shot - to be honest I never use the automatic stuff and always send RPCs or do my own serialization (and have more recently switched to using Photon for that matter).
I have seen the massive forces that can be applied to "other" objects when you move stuff yourself.
What data type are you using for the position of each object, are they just Vector3 or are you using the Vector3m for them as well? And I don't mean the final gameobject.transform.position for Unity's rendering of the object, I mean the position you store for each object as it moves through your huge scene before you reconcile it down to the single precision Unity needs?
If you are only using single precision for the position of each object, that would cause issues with their positioning.
EDIT: Never$$anonymous$$d, I think I misread what you said. So you are using a Vector3m for each object with it's precision placement relative to the origin?
I tried to describe the positional data type in my original question. I see that I have failed, and will edit the question accordingly.
Anyway, I am using a custom decimal
type vector, Vector3m
. That has 28 significant digits of precision, which ought to be enough :)
Your answer
Follow this Question
Related Questions
Did not find target warning when using uNet 3 Answers
Changing rooms and spawning players with Multiplayer Example 2 Answers
In unity3d client “push” an object with a rigidbody2d slower than the host 0 Answers
Client Getting Tile Info on Top Down Game 0 Answers
Material Data over Network (Multiplayer) 0 Answers