Closed TheFacto closed 6 years ago
I'm having the same issue as this on a Linux machine (same version of Godot) in GDScript.
Making use of force_raycast_update
doesn't seem to alleviate the problem either.
I use raycasts for moving across terrain in a 2D platformer. As long as the colliding body against the raycast is a StaticBody
, my collisions are fine. With any moving scenes, however, the reported collision points lag one frame behind.
Digging around in the source code for a bit, I found a comment that reads
//not quite correct, should compute the next matrix..
In collision_object_2d_sw.cpp
CollisionObject2DSW::_update_shapes()
The same comment is also present in
CollisionObjectSW::_update_shapes()
and the_update_shapes_with_motion()
functions
Is this comment implying that updating collisions for all CollisionObjects are a frame behind? That doesn't seem super likely to me, but I do wonder what the intent is...
EDIT
The purpose of _update_shapes appears to be to refresh the cached data stored in Rect2 aabb_cache
. In the header file, the comments indicate that aabb_cache
is used for rayqueries.
I'm not entirely sure how one would compute the 'next' matrix (maybe that's what the real problem is here). Anyone have any insights?
After toying with this some more, I've noticed this bug only occurs 'sometimes' With certain scenes, Raycast2Ds will always report the correct collision point with another scene. With certain other scenes, they will always report the scene's position in the previous frame.
One instance of a scene can always be correct, whereas another identical instance of the scene will always lag one frame behind.
It leads me to believe that perhaps this bug is caused by the order in which scenes are updated. If a scene that would collide with a RayCast2D has already had its movement applied, then the RayCast2D will correctly intersect with it Whereas if the scene in question will be moved after the intersect_ray is called, then the RayCast2D will lag one frame behind
Have you tried moving the transform.origin of the body state instead? setting position may not update the body state as fast as you want (or at all in some cases).
Not entirely sure how to set the origin correctly vs setting the position
Currently, I update scenes by what is intuitive to me.
For the player, I use a KinematicBody2D and call move_and_slide,
in addition to manually setting the position afterward via a few RayCast2Ds
When setting the position manually, I'll use either position
or global_position
Some scenes (like kinematicBodies acting as floating platforms) do not set their own position or call move_and_slide
, but are moved by parent nodes that rotate, follow a path, or move linearly
When landing on a floating platform that moves, the player RayCasting against the moving platform will report an incorrect position for certain combinations of player and moving platform (which I think is based on the update order).
How would setting the transform.origin help? What's the difference between setting the position vs setting the origin?
Setting position does not affect the body state immediately and is possible that rays are failing for that reason. If that is the case, then bodies may need a better method to sync the state to the Node transform
To modify the state's transform, use (the C# equivalent of) Physics2DServer.body_get_direct_state
for the state, then just state.transform.origin
to move it.
I suspect that this is what may be happening and the way to deal with this could have room for improvement.
I'm able to trigger this behaviour based on how I order the player and moving platform scenes If the player is 'higher' than the FloatingPlatform scene in the scene tree view like so: O - root | O - Player | O - Raycasts | |
---|---|---|---|
O - RotatingJoint | |||
O - FloatingPlatform |
Then the raycast from the player is always correct. If I change the order so that the player is 'lower' than the FloatingPlatform scene like so: O - root | O - RotatingJoint | O - FloatingPlatform | |
---|---|---|---|
O - Player | |||
O - Raycasts |
The raycast is always one frame behind.
Currently, there is no script attached to the FloatingPlatform scene. Per your direction, I attached the following script to it
extends KinematicBody2D
func _process(delta):
var state = Physics2DServer.body_get_direct_state(get_rid())
#If this isn't how I'm supposed to set the origin, by all means let me know
state.transform.origin = position
And ordered the scene so that the Player is 'lower' (thus triggering the weird RayCast behaviour) Unfortunately, the Raycasts still 'lagged' one frame behind the actual position
Since this behaviour occurs based on how the scenes are ordered, it seems like the FloatingPlatform scene simply hasn't updated at all when the Player RayCast makes it's check when it's 'higher'.
This is not a bug, for performance reasons you should not expect objects to update their position in the physics immediately after you move them. Transforms are accumulated and then set.
Probably you could try call_deferred after you move an object if you want to do a raycast.
I was thinking, maybe a method to force an object update could be added, since this is not the first time it is asked for.
fixed via 74359a1d1
Godot version:
OS/device including version:
Issue description: When using
IntersectRay()
, it appears that it is using the positions of collidable objects at the start of the_PhysicsProcess()
. I have a case where I first move an object viaSetPosition()
and subsequently callIntersectRay()
and expect that to collide with the object at its new position. I realize this may not be worded clearly, so for sake of clarity, allow me to bullet-ize these statements.Platform
at position(0, 0)
Platform
to position(0, 10)
IntersectRay()
to check where aPlatform
isPlatform
were at position(0, 0)
Please pardon me, I realize this may be working as expected, so maybe I'm asking for some sort of enhancement? I basically followed a 2D Unity tutorial using raycasts and ported that over to Godot using
IntersectRay()
and encountered this situation.Steps to reproduce: Please see minimal reproduction project.
Minimal reproduction project: raycast-sub-frame-check.zip