1
\$\begingroup\$

I'm developing a billiard game my problem is I don't know how can I sync balls in network

I use forge for networking but feel free to answer photon or unet because I know them.

enter image description here

What I tried

1.sending position and rotation of each ball in network

2.sending force direction and Intensity inside network

enter image description here

networkObject.SendRpc(RPC_SHOOT,Receivers.AllBuffered,force);

    public override void Shoot(RpcArgs args)
    {
       Vector3 Force = args.GetNext<Vector3>();
       GetComponent<Rigidbody>().AddForce(Force);
    }

I don't know why but when I send force direction and Intensity in network sometimes Physics is different! I asked this question in forge forum and they tell me:

It's non-deterministic It's how most physics simulations work Because of floating point inaccuracies and different CPU architectures and a whole load of other factors That's how PhysX works Well PhysX is technically deterministic for the same inputs But all inputs have to be identical

source is available:

https://github.com/smkplus/BilliardNetwork

\$\endgroup\$
5
  • \$\begingroup\$ Hint #1: "all inputs have to be identical". If you can provide that - it could work. Alternatively - Use one master server/host and do all the simulation there and send out only the results to other peers. \$\endgroup\$
    – Kromster
    Commented Apr 11, 2019 at 5:41
  • \$\begingroup\$ Thanks for quoting the same quote that is already in the question that I quoted my hint from ;-) They key thought is - if you can guarantee ALL identical inputs, the lib promises to be deterministic. In my Win32 experience, if you set CW8087 identical - all FP calculations are identical. However that could be different in your case. Hence I'm not posting this as an answer. Latter part is more solid though - get the authoritative master/host and sync from it. \$\endgroup\$
    – Kromster
    Commented Apr 11, 2019 at 6:06
  • \$\begingroup\$ @Kromster thanks I will test it but I'm not sure that it works.I hope you give me better solution.I have an Idea in Unity 2018.3 there is feature that predict the physic my question is can I send the prediction to opponent? \$\endgroup\$ Commented Apr 11, 2019 at 6:12
  • \$\begingroup\$ @Kromster what is CW8087?! \$\endgroup\$ Commented Apr 11, 2019 at 6:19
  • \$\begingroup\$ @Kromster it's strange I run game in local network and physics aren't same \$\endgroup\$ Commented Apr 11, 2019 at 6:29

2 Answers 2

1
\$\begingroup\$

In UNET I’d just add a Network Transform to all the balls and that would easily take care of position and rotation. I’m not sure about forge though.

If that’s not an option, why don’t you just use something like RPC to add force, the problem could be that physics might act a bit different for both clients though.

So another option could be to create a separate game object to store ball positions, and at the end of every turn they would get updated by the last player, and then checked on each client if the positions of the balls are the same as values, if not then move them.

Hopefully this helps you, that was just some ideas.

\$\endgroup\$
2
  • \$\begingroup\$ it isn't good idea because maybe one ball goes to the hole! please play flyordie.com/snooker you can see everything is sync but I don't know why unity physic is different.also I tested offline I use same force direction and intensity but sometimes physic is different this is mean unity physic is non-deterministic. \$\endgroup\$ Commented Apr 11, 2019 at 12:19
  • \$\begingroup\$ if unity physics is different for you, then maybe your code is not in FixedUpdate or doesn't use DeltaTime where required \$\endgroup\$
    – John Smith
    Commented Jul 5, 2019 at 19:23
1
\$\begingroup\$

In a networked scenario, you should not try to rely on physics determinism to keep your simulation in sync.

Even if both players are running identical binaries on identical chips, the difference of a single fixed timestep due to network latency, or a single object being spawned in a different order due to any optimizations happening in the engine's internals, is enough to introduce divergence.


Since billiards is a turn-based game, the simplest and most robust approach is to alternate authority over the simulation.

The player who takes the shot simulates the physics locally, and sends position & orientation updates to all other clients, who are for the moment just spectators.

Each spectator maintains a buffer of recent updates from the current player, and uses that buffer to show a state some time in the past. Not far - just enough to be able to absorb the occasional missed or delayed packet without visibly stuttering. This lets them always show an interpolation between two actual positions & orientations that occurred in the current player's simulation - they never need to extrapolate or simulate the behaviour themselves, and the balls always end up exactly where the current player's sim settled.

You may need to adjust the interpolated position slightly, to ensure a ball doesn't sink into the table on its way into a pocket, or to ensure the ball doesn't take a shortcut when changing direction, blunting what should have been a sharp collision, but these are purely visual fix-ups that don't affect the final gameplay state of the table in time for the player's next turn.

Then you switch authority and the next player takes the shot.

Note that this only works if you're willing to trust each client to fairly report their play. If hacking is a concern for your game, then you'll want to use an authoritative server under your control, and let all players see a copy of the simulation from the recent past. You can a wind-up animation of the pool cue to cover the latency before the first results from the server are available.


A more robust, but also more intensive solution is to compute the trajectories yourself, so you're not at the whims of a fully general physics solver, and can control the operation explicitly. I wouldn't do this for most games, but for billiards the problem space is reasonably small and well-studied, so it would be feasible to write a "billiards engine" that solves just this case exactly the way you want it.

Since you're no longer bound to iteratively approximating the outcome frame by frame, you could have one client compute the full future of the table at the moment the ball is struck, and transmit the exact sequence of actions to the other clients like a set of animation keyframes.

You could even use fixed point math to sidestep the complexity of getting floats to agree between binaries / differing hardware. Then the player could simply send their action with the pool cue, and all spectators (or the central server) can independently reproduce the outcome of that action (and check each others' work to spot cheating).

\$\endgroup\$
3
  • \$\begingroup\$ thanks @DMGregory I will test it.I tried sending position and rotation but problem is because of latency interpolation isn't good idea.sometimes ball before colliding to the wall interpolate to another direction.I will try recording animation of balls and sending it to the opponent. \$\endgroup\$ Commented Apr 12, 2019 at 6:33
  • \$\begingroup\$ another solution is using fake physic for example calculate Vector3.Reflect but I haven't enough time to make it. \$\endgroup\$ Commented Apr 12, 2019 at 8:46
  • \$\begingroup\$ What you do in that case (to solve visible interpolation artifacts) is also send velocity with each snapshot. Instead of interpolating position directly end to end, you interpolate through the corner point at the intersection of the before & after velocity lines. That way your collisions stay sharp. \$\endgroup\$
    – DMGregory
    Commented Apr 12, 2019 at 11:31

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .