-
-
Notifications
You must be signed in to change notification settings - Fork 98
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
Add ability to simulate physics manually/multiple times at once #2821
Comments
This comment has been minimized.
This comment has been minimized.
How does one achieve this? Does this require implementing your own physics / movement system? |
I don't know exactly and am not sure if there are any example projects that do this, but I've definitely heard of people doing it. If all else fails, using client-side physics with server-side checks can be a viable alternative in some cases (on top of using less resources on the server). |
@Calinou I know the Godot core engineering team has a lot going on but it would help the community if you share examples of how things can be done beyond just ‘it can be done’. We’ll learn from it and waste your time less. |
I really have no idea how it can be done, but I can attest that it has been done in the past with varying degrees of success. I don't have links to any examples around, simply because people working on multiplayer games generally don't have time to publish reusable example code. |
I bashed my head against my project a bit more and came up with a solution that works in my case I had incorrectly assumed that multiple calls to The actual issue for me was that I fixed this and matched the two back up by removing the _process delta and applying the _physics delta like so:
|
Depending on the physics API you use, in some cases it's not possible to implement this (in godot physics) without additional support directly in the physics server. If using godot physics, (any godot physics engine), in order to reset to a past known state and fast-forward simulate (running multiple steps in quick succession over the course of a single engine iteration) to a previous forward-predicted time frame, you just need to ability to step a space manually (assuming you've built your own system to replay inputs per step). This has been discussed previously in a few other issues, but I believe it's on the radar to add the functionality to be able to step a space manually to the physics server api. In our private fork, we started by simply adding a few additional functions to the physics server that allowed one to explicitly manually step a physics space provided the space's RID and delta time (pretty easy addition to the physics server API). But we've since scraped that, and moved to using a completely different physics engine entirely (box2d), which we've exposed support for manual stepping of the box2d world (physics space), and just control the rewind/reset -> fast-forward simulation directly. |
@jordo I’m not that deep into customization yet, how do you add a custom physics engine to Godot? Feel free to post on Discord and Reddit too. It will make killer content |
I've also been working on implementing rollback network synchronization, and I'm not sure it's currently possible while using Godot's built-in physics system. The physics engine appears to not process collisions (ie. a I'm going to keep experimenting with this over the next couple week, and if I come up with a way to do this, I'll report back. |
There's a Box2D C++ module for Godot that jordo likely uses. 🙂 Looks like the implementation is not tied to Godot physics server, but I think it would also be possible to integrate Box2D as a physics 2D backend in Godot (likely with limitations, because Godot's physics server API does not provide the many features Box2D provides). |
I've been working on implementing rollback network synchronization for the past few weeks, and I can now say definitively, that it's not possible to do with Godot's physics engine, without exposing a method like Purely for demonstration purposes, here's a PR that adds a I'm sure that the implementation is terrible, and I don't ever expect it to be committed. :-) My goal is to argue for this proposal, that we add something like this to Godot's physics API. For debugging, I've setup my project to rollback 5 frames every frame, just to see what breaks when rolling back. Here's what happens without You can see the explosion appears where the bullet was 5 frames ago. This is because the bullet was overlapping the tree according to Godot's physics engine, then we rolled back 5 frames, except Godot's physics engine still considered the bullet as colliding because we were unable to step it forward after changing it's position. Here's what happens when calling You can see the explosion appears right on the tree where you'd expect it! So, in Godot 3.x, the only way to implement rollback is by either:
Now, in Godot 3.x, option nr 2 is the only realistic choice, because this network synchronization technique depends on the physics engine being deterministic, and Godot's physics engine isn't. However, my understanding is that in Godot 4.x, the plan is that we'll be able to create new physics engines that can be swapped in instead of Godot's default. In that case, someone could implement a deterministic physics engine, and then all we need is this additional bit of API added. So, I'd like to propose that we re-open this proposal, so that we can discuss the possibility of adding this API to Godot 4.x. |
@pouleyKetchoupp What are your thoughts about adding something like this to the Physics API for Godot 4.x? |
Some time ago I asked Camille about the implementation of #1373 that aims at the same result, something similar to Physics.Simulate() by exposing some internal variables and methods, I faced the same need to manually process physics steps, in my case this could be useful to bake / predict trajectories for rigid body motion on a parallel physics layer, the answer was that it is on his todo list, likely for Godot 4.1 since there are bugs on both 2d and 3d to be squashed first. |
Yes, I can confirm this feature is on the radar of the core devs, and the general idea is already approved. It will just need further discussion to decide how to implement it in a way that makes sense for all the different use cases, so 4.1 seems like a good estimate for now. |
In case this is interesting/useful for other folks who find their way here: for my game, I ended up implementing a custom deterministic 2D physics engine as a Godot module. It's Open Source (MIT license) and you can find the project page here (with some pre-built binaries for Windows, Linux, MacOS and HTML5): https://gitlab.com/snopek-games/sg-physics-2d/ ... and here's a tutorial for getting started with it that I just published today: |
I'm building a networked game. Currently I'm wrapping Bepu Physics in C# so that I can step the physics manually (and also so I can create multiple physics worlds), but I'd love to remove the requirement for Bepu and make my networking solution more widely available and applicable. Regardless of whether you're using a deterministic physics engine, if the client predicts physics (which is true in quite a lot of games, even when the player is a non-rigidbody character controller), it's necessary to be able to step the physics engine manually to handle reconciliation. Just thought I'd mention that since @dsnopek seemed to imply that predicting physics is only useful when you use a deterministic physics engine (which would, in turn, suggest that being able to step the physics engine manually is only useful if it's also deterministic, which isn't true). As long as you're sending state+input instead of only input and the physics engine comes up with similar results across machines most of the time (which basically all physics engines do), you can call it "close enough", and only make rollback-corrections when the divergence gets too high (or you can accumulate divergence to trigger rollbacks after some time even when divergence isn't continuously increasing). |
So this was targeted at 4.1 which is now officially released...does it need to be retargeted then to 4.2 or something? Still very interested in this to be able to lag compensation! |
The milestone was set a long time ago before the new release policy, so it's not relevant anymore. I've moved it to |
FYI It looks like someone implemented a version of this, available in a PR godotengine/godot#76462 |
Also a similar request made in godot-jolt: godot-jolt/godot-jolt#623 |
This has been requested so much for the past 3 years or so. Is there any central way to track it? It makes no sense to not support something when so many hacks have to be discussed. |
This proposal is the central way to track it 🙂 Individual PRs are where the implementation is discussed, but the feature itself must be discussed in the proposal. |
I want to reference this comment since the original author didn't repost it in this thread.
The method would still work as intended, since people can pass the delta from the context in which they're calling the method, and if that's too big of a change, we can just make the parameter optional and retain the original behavior if it is not passed PS: I can personally submit a PR that adds the parameter for both the 2D and 3D versions of the method, if there's interest for it |
This might be a bit out of scope, but I guess that's up to everyone here to decide: Would it be sensible to also expose a way to request My reasoning here is that for a "full" manual simulation of a physics subloop, you would have to do all of these (at least for the nodes you're interested in) in order to replicate the engine's behavior:
*: I purposely left out scene tree timers and tweens to simplify the discussion, although maybe a way of manually stepping them should also be included for full control. Then again, that makes me think that maybe this indeed is out of scope. On that same vein, should we expose a way of triggering the "internal physics process" callbacks of specific nodes? Otherwise, we wouldn't be able to manually step timer nodes and other such things. Currently, it can be done via notifications, but I assume that a fully fledged "manual stepping" feature shouldn't rely on such things, and also, we don't have control over the delta in that case. At the very least, documentation surrounding manual stepping should ideally expose all these caveats and how to work around them. A breakdown of how the physics subloop works and how to simulate each step in code is fundamental for a feature like this to make sense IMO. I did some legwork in that regard some days ago. It isn't exhaustive but it I think it's a good start. It's focused on the 2D physics server but it should be very similar (if not the same) for the 3D one: Link |
There's another issue that I'm not sure is being discussed elsewhere (please correct me if I'm wrong). The physics server has internal state that is used for things like collision signals (it needs to know which shapes are currently inside an area to know whether a shape just entered or left). That state isn't readable or writable in the public API, which means that even if we can step the physics server manually, rollback can't be properly implemented (or at least you can't rely on collision signals if you do). Take this example with an area A and shape S. The list of contained shapes of area A according to the physics server on every step will be denoted by square brackets ([ ] denotes empty, [ S ] denotes that S is contained)
As you can see, the second time tick 1 is simulated, the signal won't get emitted even though the shape just entered the area in the previous tick. |
@monitz87 Ahhhhh this is a really good point. Hmm, so this PR can't be merged yet then. Maybe I'll take a deeper look at the physics engine integration when I get some time. |
No idea if the following helps with the multiplayer issues, but it has allowed me to "step ahead" one physics object in Godot 4.2. I landed here as I wanted to create a "trajectory indicator" for my Peggle-alike game. The most accurate way to do this is to simply create an invisible duplicate of the ball and step it forward, recording each step, which can then be displayed as a dotted line. In the _integrate_forces code below I use the same "_apply_constant_forces" function for both the real and dummy balls (to ensure consistency, and because I have yet to add angular force). Of course the downside of this is that it can take multiple frames to complete the step ahead if collisions occur, for my game this is not an issue (and actually looks quite good as the trajectory indicator grows in steps). Hopefully some of the other people here will find this useful:
|
Describe the project you are working on
Networked player movement with client-side prediction
Describe the problem or limitation you are having in your project
Quick summary of client-side prediction:
In Godot currently, there is no way to re-simulate these pending inputs at a single moment in time
Describe the feature / enhancement and how it helps to overcome the problem or limitation
Allowing Godot users to manually execute / simulate physics steps would make the above method of achieveing client-side prediction possible
Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams
https://docs.unity3d.com/ScriptReference/Physics.Simulate.html
If this enhancement will not be used often, can it be worked around with a few lines of script?
I am not aware of any workarounds that don't involve writing your own custom physics system within Godot
Is there a reason why this should be core and not an add-on in the asset library?
This functionality would give the user control of when Godot's physics executes - IMO it is very closely related to existing core functionality and wouldn't make much sense to segregate as an addon
Related issues:
godotengine/godot#25068
godotengine/godot#24769
The text was updated successfully, but these errors were encountered: