godotengine / godotengine/godot
intersect_shape not working with Area3D in @tool
- Dominant language
- C++
- Stars
- 117k
- Forks
- 26.8k
- PR merge metrics
- PR metrics pending
Description
### Tested versions
Reproducible in v4.3.dev2.official [352434668]
### System information
Godot v4.3.dev2 - Ubuntu 22.04.3 LTS 22.04 - X11 - Vulkan (Forward+) - dedicated NVIDIA GeForce RTX 2060 (nvidia; 535.146.02) - Intel(R) Core(TM) i5-9400F CPU @ 2.90GHz (6 Threads)
### Issue description
In the code below, I place collision nodes (under an Area3D) at each of the four boxes. The last should cause an intersection, but if one happens at all, it seems random. This is in a plugin/tool and I am trying to find a way to scatter meshes but avoid overlaps.
I have spent a week trying various ways (even using PhysicsServer3D) but nothing works. I have asked online and in the Godot Forums, but there has been no progress. I'm not 100% sure this is a bug, but I'm guessing it is.

The code is:
````
@tool
extends Node3D
## Area intersection isue
##
## Trying to make an Aread3D by using nodes and
## test for intersection with a box shape.
##
## Open the scene and click the bool Tog in the inspector
## Observe the printed output.
##
## I expect to see:
## *****************************
## one
## two
## three
## TEST HIT
## Bingo!
var A:Area3D
var state:PhysicsDirectSpaceState3D
@export var WTF:bool:
set(b):
WTF = false
await set_state()
await wtf()
func set_state():
state = null
await get_tree().physics_frame
if not state:
state = get_world_3d().direct_space_state
func wtf():
await create_area3d_node()
await node_probe()
func create_area3d_node():
print()
print("*****************************")
var _a = find_child("AREANODE")
if _a:
remove_child(_a)
_a.queue_free()
A = null
A = Area3D.new()
A.name = "AREANODE"
add_child(A)
A.set_owner(self.owner)
await get_tree().physics_frame
func node_probe():
var box:BoxShape3D
# make a shape, the same size as b
var poke = [$one, $two, $three]
for b in poke:
print(b.name)
box = BoxShape3D.new()
box.size = b.mesh.size
var newt:Transform3D = b.transform
var coll:CollisionShape3D
coll = CollisionShape3D.new()
coll.name = b.name
coll.transform = b.transform
coll.shape = box
A.add_child(coll)
coll.set_owner(A.owner)
await get_tree().physics_frame
#As per docs
var params:PhysicsShapeQueryParameters3D = PhysicsShapeQueryParameters3D.new()
var shape_rid = PhysicsServer3D.box_shape_create()
PhysicsServer3D.shape_set_data(shape_rid, $overlapper.mesh.size)
params.shape_rid = shape_rid
params.transform = $overlapper.transform
params.collide_with_areas = true
params.collide_with_bodies = false
print("TEST HIT")
var surrounds = state.intersect_shape(params, 6)
PhysicsServer3D.free_rid(shape_rid)
if surrounds:
print("Bingo!")
````
### Steps to reproduce
Try the MRP below.
### Minimal reproduction project (MRP)
https://gitlab.com/dbat/server_area_issue
### Update
As requested, the code does work *outside* the editor. I have pushed the gitlab repo with that test code too.
Output for reference:
```
one
two
three
TEST HIT
Bingo!
```
### Latest
This was bumped to a proposal discussion. I started it here: https://github.com/godotengine/godot-proposals/issues/8963
(ETA, redid the proposal because I posted in the wrong dimension.)
### Tentative solution
https://github.com/godotengine/godot-proposals/issues/8963#issuecomment-1910048689
> One thing you can do to accomplish a lot of intersection features, with some trickery as well, is using [culling](https://docs.godotengine.org/en/stable/classes/class_renderingserver.html#class-renderingserver-method-instances-cull-convex) in the rendering server, this is used in some editor plugins as far as I can tell (it even says: `This function is primarily intended for editor usage. For in-game use cases, prefer physics collision.`, so probably the appropriate solution, do test and see)
https://github.com/godotengine/godot-proposals/issues/8963#issuecomment-1910286572
> The functions that AThousandShips linked are basically the API to query the visual rendering scenario for its spatial info.
>
> E.g. what visuals with a position are inside some convex plane shape, what intersects with a raycast. Not using the physics engine that only has information about physics shapes, but the rendering that only has information about visual geometry and other render objects like lights.
>
> With the ids returned those ids can be used with the ObjectDB / GlobalScope.instance_from_id () to get the actual SceneTree object behind that id, e.g. the node.
>
> It is not something that should be done at runtime, hence the "Use physics for in-game" hint, because it forces stalls and updates on the RenderingServer. For inside the Editor that performance is not much of a concern as long as you do not fire those functions every single frame like mad.
### Update on `RenderingServer.instances_cull_aabb`
There's a bug:
https://github.com/godotengine/godot/issues/87709
Contributor guide
Research direction
Reproduce the behavior with the linked minimal reproduction project, comparing the @tool and runtime cases around PhysicsDirectSpaceState3D.intersect_shape and PhysicsServer3D. Read proposal 8963 and issue 87709, then establish whether editor-time physics intersections should work and what behavior is considered done.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- game-dev
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100