get_gravity() doesn't update after move_and_collide()
Tested versions
v4.3.stable.mono.official [77dcf97d8]
System information
Godot v4.3.stable.mono - Windows 10.0.19045 - Vulkan (Forward+) - dedicated NVIDIA GeForce GTX 1060 6GB (NVIDIA; 31.0.15.5244) - AMD Ryzen 5 2600X Six-Core Processor (12 Threads)
Issue description
PhysicsBody2D.get_gravity() is not updating its value after I call move_and_collide()
I'm doing multiple iterations of move_and_collide() in one frame to draw a Line2D path in the direction the object will be going and stop at any collision point. The problem is that get_gravity()'s value doesn't change at all over the course of the iterations, it stays constant the entire time. I'm using Area2D nodes as gravity points, so the gravity value should never be constant for a moving object, and without get_gravity() updating I can never actually predict the path my object will take in the future.
If this is intended behavior, there's no indication in the documentation. It just says Returns the gravity vector computed from all sources that can affect the body which is not the behavior I'm observing.
Steps to reproduce
Use multiple move_and_collide() iterations in one frame whilst the object is inside an Area2D with gravity_point enabled and observe that the value returned from get_gravity() is the same for every iteration.
Minimal reproduction project (MRP)
I suspect this is due to delays in handling some updates, will test the MRP and confirm but this might be something to document as a limitation
See also:
- https://github.com/godotengine/godot/issues/87996
I'm wondering if the implementation in https://github.com/godotengine/godot/pull/83087 would be better, given the issues with get_gravity. @mihe thoughts?
This specific problem wouldn't be fixed by something like #83087. As hinted at by @AThousandShips already, the area overlaps are evaluated as part of stepping the physics simulation, which you'd need to have up-to-date no matter which approach you take.
I'm not sure if this is really documented anywhere, but this limitation applies to a number of physics-related things in Godot, like the contact reporting and the various signals emitted (e.g. body_entered). I wouldn't really consider this a bug.
The only way I can see this being done (short of custom stepping + rollback, which isn't a thing in Godot, and seems overkill here) would be to use intersect_shape with collide_with_areas set to true, to figure out what areas you'd be overlapping with at that point and then calculate the total gravity yourself based on their priority and gravity_space_override, but that is not trivial.
Also (and this is borderline off-topic) there is another bug lurking in the current implementation of get_gravity, which I touched upon briefly here, and which would be fixed by something like #83087, where if your CharacterBody3D (or some other kinematic body) is just standing perfectly still, and you have some Area3D with gravity_space_override moving around and entering/exiting the body, then the gravity reported by get_gravity will become stale, as gravity is only computed for active/awake bodies, and kinematic bodies are only considered active/awake during the single tick after which they moved.
I need to make a separate issue for that.