diff --git a/doc/classes/Physics2DDirectSpaceState.xml b/doc/classes/Physics2DDirectSpaceState.xml
index 7712da0f9682..a18dd996ac4e 100644
--- a/doc/classes/Physics2DDirectSpaceState.xml
+++ b/doc/classes/Physics2DDirectSpaceState.xml
@@ -109,12 +109,12 @@
- Intersects a ray in a given space. The returned object is a dictionary with the following fields:
+ Intersects a ray in a given space. If the ray originates inside one or more objects, the first detected object will be selected. The returned object is a dictionary with the following fields:
[code]collider[/code]: The colliding object.
[code]collider_id[/code]: The colliding object's ID.
[code]metadata[/code]: The intersecting shape's metadata. This metadata is different from [method Object.get_meta], and is set with [method Physics2DServer.shape_set_data].
- [code]normal[/code]: The object's surface normal at the intersection point.
- [code]position[/code]: The intersection point.
+ [code]normal[/code]: The object's surface normal at the intersection point. If the ray originates inside the object, this will be a zero length [Vector2].
+ [code]position[/code]: The intersection point. If the ray originates inside the object, this will be the ray's origin.
[code]rid[/code]: The intersecting object's [RID].
[code]shape[/code]: The shape index of the colliding shape.
If the ray did not intersect anything, then an empty dictionary is returned instead.
diff --git a/doc/classes/PhysicsDirectSpaceState.xml b/doc/classes/PhysicsDirectSpaceState.xml
index a8bd07cc9445..cba9ee718220 100644
--- a/doc/classes/PhysicsDirectSpaceState.xml
+++ b/doc/classes/PhysicsDirectSpaceState.xml
@@ -65,11 +65,11 @@
- Intersects a ray in a given space. The returned object is a dictionary with the following fields:
+ Intersects a ray in a given space. In Godot physics, if the ray originates inside one or more objects, the first detected object will be selected. In Bullet physics, these objects are ignored. The returned object is a dictionary with the following fields:
[code]collider[/code]: The colliding object.
[code]collider_id[/code]: The colliding object's ID.
- [code]normal[/code]: The object's surface normal at the intersection point.
- [code]position[/code]: The intersection point.
+ [code]normal[/code]: The object's surface normal at the intersection point. In Godot physics, if the ray originates inside one or more objects, this will be a zero length [Vector3].
+ [code]position[/code]: The intersection point. In Godot physics, if the ray originates inside the object, this will be the ray's origin.
[code]rid[/code]: The intersecting object's [RID].
[code]shape[/code]: The shape index of the colliding shape.
If the ray did not intersect anything, then an empty dictionary is returned instead.
diff --git a/doc/classes/RayCast.xml b/doc/classes/RayCast.xml
index ec4d45fd5494..38acc0245da8 100644
--- a/doc/classes/RayCast.xml
+++ b/doc/classes/RayCast.xml
@@ -4,7 +4,7 @@
Query the closest object intersecting a ray.
- A RayCast represents a line from its origin to its destination position, [code]cast_to[/code]. It is used to query the 3D space in order to find the closest object along the path of the ray.
+ A RayCast represents a line from its origin to its destination position, [code]cast_to[/code]. It is used to query the 3D space in order to find the closest object along the path of the ray. In Godot physics, if the ray originates inside one or more objects, the first detected object will be selected. In Bullet physics, these objects are ignored.
RayCast can ignore some objects by adding them to the exception list via [code]add_exception[/code] or by setting proper filtering with collision layers and masks.
RayCast can be configured to report collisions with [Area]s ([member collide_with_areas]) and/or [PhysicsBody]s ([member collide_with_bodies]).
Only enabled raycasts will be able to query the space and report collisions.
@@ -54,6 +54,7 @@
Returns the first object that the ray intersects, or [code]null[/code] if no object is intersecting the ray (i.e. [method is_colliding] returns [code]false[/code]).
+ In Godot physics, if the ray originates inside one or more objects, the first detected object will be returned. In Bullet physics, these objects are ignored.
@@ -78,6 +79,7 @@
Returns the normal of the intersecting object's shape at the collision point.
+ In Godot physics, if the ray originates inside one or more objects, a zero length [Vector3] will be returned. In Bullet physics, these objects are ignored.
@@ -85,6 +87,7 @@
Returns the collision point at which the ray intersects the closest object.
+ In Godot physics, if the ray originates inside one or more objects, the ray origin will be returned. In Bullet physics, these objects are ignored.
[b]Note:[/b] This point is in the [b]global[/b] coordinate system.
@@ -93,6 +96,7 @@
Returns whether any object is intersecting with the ray's vector (considering the vector length).
+ [b]Note:[/b] In Godot physics, if the ray originates inside one or more objects, [method is_colliding] will return [code]true[/code]. In Bullet physics, these objects are ignored.
diff --git a/doc/classes/RayCast2D.xml b/doc/classes/RayCast2D.xml
index 006a18b34773..bc491dbb489c 100644
--- a/doc/classes/RayCast2D.xml
+++ b/doc/classes/RayCast2D.xml
@@ -4,7 +4,7 @@
Query the closest object intersecting a ray.
- A RayCast represents a line from its origin to its destination position, [code]cast_to[/code]. It is used to query the 2D space in order to find the closest object along the path of the ray.
+ A RayCast represents a line from its origin to its destination position, [code]cast_to[/code]. It is used to query the 2D space in order to find the closest object along the path of the ray. If the ray originates inside one or more objects, the first detected object will be selected.
RayCast2D can ignore some objects by adding them to the exception list via [code]add_exception[/code], by setting proper filtering with collision layers, or by filtering object types with type masks.
RayCast2D can be configured to report collisions with [Area2D]s ([member collide_with_areas]) and/or [PhysicsBody2D]s ([member collide_with_bodies]).
Only enabled raycasts will be able to query the space and report collisions.
@@ -74,14 +74,14 @@
- Returns the normal of the intersecting object's shape at the collision point.
+ Returns the normal of the intersecting object's shape at the collision point. If the ray originates inside the object, a zero length [Vector2] will be returned.
- Returns the collision point at which the ray intersects the closest object.
+ Returns the collision point at which the ray intersects the closest object. If the ray originates inside the object, the ray's origin will be returned.
[b]Note:[/b] this point is in the [b]global[/b] coordinate system.
diff --git a/servers/physics/space_sw.cpp b/servers/physics/space_sw.cpp
index ba1070a3cb8b..c12ea33186de 100644
--- a/servers/physics/space_sw.cpp
+++ b/servers/physics/space_sw.cpp
@@ -136,8 +136,15 @@ bool PhysicsDirectSpaceStateSW::intersect_ray(const Vector3 &p_from, const Vecto
Vector3 shape_point, shape_normal;
- if (shape->intersect_segment(local_from, local_to, shape_point, shape_normal)) {
-
+ if (shape->get_closest_point_to(local_from) == local_from) {
+ min_d = 0;
+ res_point = local_from;
+ res_normal = Vector3();
+ res_shape = shape_idx;
+ res_obj = col_obj;
+ collided = true;
+ break;
+ } else if (shape->intersect_segment(local_from, local_to, shape_point, shape_normal)) {
Transform xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx);
shape_point = xform.xform(shape_point);
diff --git a/servers/physics_2d/space_2d_sw.cpp b/servers/physics_2d/space_2d_sw.cpp
index 4748094fe26a..2bc3f1f6ca3f 100644
--- a/servers/physics_2d/space_2d_sw.cpp
+++ b/servers/physics_2d/space_2d_sw.cpp
@@ -159,8 +159,15 @@ bool Physics2DDirectSpaceStateSW::intersect_ray(const Vector2 &p_from, const Vec
Vector2 shape_point, shape_normal;
- if (shape->intersect_segment(local_from, local_to, shape_point, shape_normal)) {
-
+ if (shape->contains_point(local_from)) {
+ min_d = 0;
+ res_point = local_from;
+ res_normal = Vector2();
+ res_shape = shape_idx;
+ res_obj = col_obj;
+ collided = true;
+ break;
+ } else if (shape->intersect_segment(local_from, local_to, shape_point, shape_normal)) {
Transform2D xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx);
shape_point = xform.xform(shape_point);