-
-
Notifications
You must be signed in to change notification settings - Fork 97
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
Clarify and clean-up how kinematic bodies uses physics state #2332
Comments
Yeah, it does seem inconsistent. After calling any move function, This could be improved by making Functions like |
Yeah that seems like the most straightforward approach. Here's some questions about the implementation:
These are mostly edge cases, but the documentation should explain how it handles them.
Unless I'm missing something obvious these methods don't exist for
I guess what I'm more interested in is knowing their acceleration. For example, if the player is on a platform that decelerates quickly I might want to launch them off the platform. While I could calculate this from the point of view of the player, there'd be a 1 frame window when I first land on the platform where I don't know it's acceleration. Alternatively I could calculate it in all the platforms, but looking at this code it seems like kinematic bodies already have enough information to calculate their acceleration, so it seems a waste to duplicate these calculations when then engine already has the information. |
Yeah I agree velocity should be from A to A6 in this case. From what I see in the internal code of the physics server, it seems that's what we could expose to scripts:
It's a good point, but it's not easy to make everything consistent between RigidBody and KinematicBody.
Ah yes you're right, I thought
There's still the possibility to add previous velocities to the API for |
Yeah I agree we don't really need previous velocities. What I'd be more interested in is a |
The use cases described in #2315 (comment) make a lot of sense: It would be interesting to check how these cases go in 2D, and in 3D once |
Physics and Reparenting KinematicBodiesAnother approach to tackle the moving platform problem is to change the KinematicBody's parent to the platform it is riding on. This is very similar to the node-ordering method since it shuffles the node tree such that platforms always execute before the bodies riding on them. I made a demo that illustrates this approach. This demo exposes another big assumption which the documentation does not mention, all physics calculations are performed using the global reference frame and many will be wrong for objects in non-stationary reference frames. Looking through the issue tracker, this seems intentional and there's no plans to change this: godotengine/godot#22904, godotengine/godot#26003. If that's the case, that leaves the node-ordering approach as the only way to write a non-trivial platformer without major changes to the current KinematicBody API (I could work around most of these issues in my demo projects, but there's still some I can't fix without writing my own While the reparenting approach seems more intuitive at first, there's some issues that I think make it harder to use in practice:
So I don't think it's necessary to support it (wouldn't hurt if it was), but it'd be good to mention in the documentation that if a KinematicBody's position is dependant on another KinematicBody, it should be placed lower in the scene tree and you can't use node parenting to solve this. Potential Solution to Reordering the Scene TreeIt feels hacky using the scene tree to control execution order, so maybe it would be better if we could assign processing priorities to nodes. This seems like an extremely useful feature and would even have many uses outside the physics engine. This would also remove the need for the In hindsight it feels like an obvious feature, so maybe there's some reason it doesn't already exist. If not, it's probably worth opening a separate issue to discuss it (I couldn't find one if it already exists). |
Another potential solution is to handle process priority manually with scripts: func _physics_process(delta):
# ...
# all the nodes that depend on the current one get processed here
for node in dependants:
node._physics_process(delta) This seems way uglier than if nodes had explicit execution priorities. |
It turns out it already exists, I just didn't look properly. You can use So with these changes it should be possibility to make moving platforms without needing |
I updated the proposal with what was discussed so far. I also added a concrete example and cleared up the explanations to clearly demonstrate the issue. |
Thanks for the update! Could you actually open an issue in the main repo that links to this proposal with the test project you've added? This example clearly shows a bug with collision detection. |
I also managed to reproduce this kind of issue between rigid and kinematic bodies: godotengine/godot#46653. Although kinematic-kinematic collisions need the most up to date positions, I think to then resolve kinematic-rigid body collisions the kinematic bodies still need to be treated as moving from the start of frame |
Any status update on this issue? I can confirm that it applies to 2D also. In 3.4 I'm having the problem of two KinematicBody2D's penetrating when they're both moving toward each other, causing my "immovable" object to be pushed during the resolution. Is there any workaround? |
@djrain There's no update at the moment, although in 4.0 you can make one of them ignore the other one completely using collision layers since they are not checked both ways anymore, which can help with the second part of your issue (immovable object being pushed). Something you can try in 3.4 is to make sure the immovable one is updated last (using node order in the tree or node process priority). It might alleviate the issue, but I'm not sure it would solve it entirely (and the kinematic bodies would still overlap for one frame). Feel free to open an issue for your case if it's easy enough to make a minimal project, since there's none for 2D at the moment. |
I entered a bug about this issue a while back and have a kind of crappy workaround here: godotengine/godot#30481 (comment) |
Describe the project you are working on
A game that uses KinematicBody nodes
Describe the problem or limitation you are having in your project
During each physics frame the state of the physics engine transitions from state
A -> B
. When working with KinematicBody the game world should go through several transition states for each KinematicBody that calls its_physics_process()
handler:A -> A1 -> A2 -> ... -> B
. However, the physics engine moves them all independently based off the snapshot it took of the world at the start of the frame (A
).Here's an example project that demonstrates the kinds of issues this causes: test-collision.zip.
In this project two cubes use
move_and_collide()
on the same frame to move towards a location where they should detect a collision, however since they don't update the world state until the end of the frame, they end up overlapping without seeing any collision.Even more confusing, the blue cube which gets processed second evaluates
RedCube.global_transform.origin
as the updated version, however it still does not collide because the physics server still uses the old one. This extends to objects velocities as well, if a KinematicBody moves during a physics frame functions likemove_and_slide()
will always get the velocity objects had at the start of the frame, even if they've moved already, which should have updated their velocity.Old explanation, slightly wrong/confusing:
During each physics frame the state of the physics engine transitions from stateA -> B
. However, when working with KinematicBody the game world goes through several transition states for each KinematicBody that calls its_physics_process()
handler:A -> A1 -> A2 -> ... -> B
.As far as I can tell, the API mostly assumes that these transition states do not exist. For example, KinematicBody objects keep track of their velocity which gets updated in between physics frames (state A and B). However, if I move a KinematicBody X it will be in a transition state An updating it's position, velocity, etc. Now if a second KinematicBody Y callsmove_and_slide()
to collide with X and queries the velocity of X, it will get the value X had in state A not state An yet the collision detection happens using the positions X and Y have in state An. To further complicate things, if Y callsmove_and_slide()
in the next frame it will end up using physics state from at least 4 different states: A, An, B, Bn.Describe the feature / enhancement and how it helps to overcome the problem or limitation
Instead of kinematic bodies moving independently, they should move based on the order they are processed, updating their positions and velocities accordingly.
Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams
Under this proposal the above example would behave like this:
Note the processing order effects the outcome, so in some cases it will be necessary to control it with
Node.process_priority
. While this may seem confusing, consider that the nodes which execute first have no way to predict what any of the nodes that follow will do. Similarly, the last nodes have no way to decide what to do until all the preceding nodes have decided.Under this proposal, it should also be possible to implement moving platforms without the
Sync to Physics
feature by setting theNode.process_priority
to achieve a similar result.If this enhancement will not be used often, can it be worked around with a few lines of script?
This can't be worked around.
Is there a reason why this should be core and not an add-on in the asset library?
This is an issue with KinematicBody API in the engine.
The text was updated successfully, but these errors were encountered: