New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Determinism of the system #155
Comments
p2.js should be fully deterministic, and work equally in different javascript VMs. (There are small differences, for example precision in the trigonometric functions, but it should not be noticeable). When do you apply the force? If you do it in the fixed step loop (in the I would love to see a working networked physics example for p2 :D Thanks for using the lib! |
Then it's me doing something wrong, this is very good news ;) I am rewinding by updating the client's state to match the server's state at a certain time if my position at that time did not match the server's position, and then fast forwarding to where I was, but I am not ensuring that the forces are applied at the same time step. And although I am correcting, not applying the force at the same timestep could cause too big corrections, hence the big jumps I get. I'll have a look into that. Thanks for your input, when I have put something together that makes sense, I'll let you know. Thanks for making the lib, it is great! On Thu, Apr 23, 2015 at 10:34 AM, Stefan Hedman notifications@github.com
|
Hi Stefan, I simplified my simulation so that the physic engine only starts (the setInterval) when I receive the force to apply (I store the force, set the interval and in the postStep event I apply the force, so at step 0, there are still no forces involved). In the post step I was also applying custom ground and air friction - it is a top down game) but I removed that to be sure it was not the cause of my problem, I just replaced it with setting a higher damping. Roughly I have a body with a circle shape being sent to collide with a plane shape. Both shapes have a different material and I created a contact material to define the collision between the two. I fixed the angle and magnitude and compute the force vector using cos and sin (on client and server, I know this could cause slight difference but unnoticeable like you said). As far as I can tell, the client and server environment are identical. Yet, what I observe is that the ball being sent on the client seems to be bouncing less on the plane than on the server, and it does so with a wider angle. I attached a beginContact event handler to inspect all data when both bodies collide. I inspected bodyA, bodyB and contactEquation on the event: everything is the same on server and client, positions, forces, bounding radiuses, aabbs, velocities, etc. Yet the resulting collision is different. Any idea what I should be looking for? Thanks a lot. PS. I also tried with and without ccdSpeedThreshold. On Thu, Apr 23, 2015 at 12:07 PM, Alexandre Soares asoares1@gmail.com
|
Very difficult to guess from here.. Maybe compare the ContactEquation objects on client/server via world.narrowphase.contactEquations? Make sure no properties differ. |
I'll try to compare everything in the postBroadphase, endContact and impact events and see if I can spot a difference in the values. Is there an event for a solver iteration (to make sure both the server and client are doing the same number of iterations in the narrowphase?) |
Not really. But you can check world.solver.usedIterations in the postStep event to check the number of iteration. Alternatively, just set solver.tolerance=0 and you'll always max out the iterations. Not performant, but you'll assure the number of iterations during testing. |
Thanks for your directions, I'll let you know when I find out what's On Tue, Apr 28, 2015 at 9:50 AM, Stefan Hedman notifications@github.com
|
Finally found it by logging all data in the impact event and comparing it between client and server. I noticed some shapes did not have their material set up on the client... I double checked many times that both server and client were setting up the ContactMaterials with the same settings, but I never checked that I was actually setting up the materials on the shape...(facepalm). Once I fixed it, it worked like a charm. Thanks for your support! |
Awesome! |
Hi, I don't want to revive the issue but I would like to make sure p2 is deterministic. I experimented such drifting myself in my own game in the past (not using p2.js) and I solved it by applying rounding at the correct place so the floating calculation remain the same on every machine. Is p2 doing something similar ? If not what make you sure p2 is deterministic ? Thanks By the way, what is the best place to ask question about p2.js. Is it through github issue like this one or is there an active community somewhere ? |
@wighawag Since p2 doesn’t rely on system timers or random number generators, a given input will yield the same output. p2 relies on the built in math functions like I’m kind of surprised about this discussion. Usually when doing networked physics simulated games, the assumption is that every client is slightly out of sync - when it’s too much out of sync it has to be corrected. In this approach, the precision of a math function will not matter much, it will just impact the amount of correction that needs to be applied. See this talk about Rocket League network code: https://youtu.be/ueEmiDM94IE Yes, I’d say the best p2.js forum is right here. |
Thanks for the answer. I did not figure out what was the exact cause of the calculation drifting in my past game. Might well have been trig functions but it could simply be some difference in float calculation. Rocket league is indeed using an authoritative server that send correction regularly. But for some game, it is better to have the client perform the full game physics deterministically with the only thing sent from server being inputs from other players (no correction need to be send ever). This allow the state to scale. You can have a gigantic state with milions of entities without having to send their data/delta over the wire except at player joining time. The trade off is usually to set a fixed input delay for all client, like 200ms so when a player does an action, its action is only performed 200ms later when server acknowledge it. This works for some game, like strategy game where input does not need to be instant. While I am not sure my game would need this, I want to explore my possibilities. If the system is fully deterministic and the client game state will be the exact same as the server. I understand the p2.js is logically deterministic but since I have seen few claim that different javascript implementation or even the same implementation running on different architecture might have floating point calculation differences due to the order in which operation can be performed, I was wondering if p2 were taking some precaution to keep determinism even in these cases. How hard would it be to use integer instead of float for p2.js ? javascript having 53 usable bit for integers, we could have enough precision still. |
Thanks for the clarification! It’s probably a lot of work to use fixed point math. JS doesn’t have operator overloading and other language features required to just switch without changing all of the code. Not to talk about the performance impact it would have. Even if it was possible, I don’t know if the simulation quality would be stable enough using reduced precision. I’ve tried switching from float32 to float16 once in another rigid body simulation project, and didn’t consider it good enough. Are there libraries for fixed point math in JS? If this really is a problem, I’d expect a few libraries to pop up.. |
The thing is that with js integer we have actually 53 bit precision so we should get better precision than float32. I might be completely wrong though :) I should have a deeper look at p2.js myself and see if it would be an achievable task. |
Hi,
I am using p2.js version v0.6.1 for a multiplayer game which runs in node.js on the server and in a browser on the client. I am running a physic simulation on the server and on the client.
I was trying to see the extent of the differences of running the "same" simulation on the server and on the client. I setup identical worlds (as far as I can tell) and I apply the same force to a circular body that bounces around on planes (limits of the world) and on other circular bodies inside the planes. On collisions, sometimes server and client are getting the exact same results. Some other times, the angle of the collisions varies roughly by as much as approximately 15 degrees (I didn't measure it, it is a visual approximation). I thought the differences would be smaller than that so that I would be able to make small corrections on the clients that would go unnoticed. That is not the case.
Is is expected behavior or am I doing something wrong (or my worlds are probably not as identical as I think - apart from the environment in which javascript is running that is)?
Thanks a lot for your time.
The text was updated successfully, but these errors were encountered: