godotengine / godotengine/godot

intersect_shape not working with Area3D in @tool

Open
#87,429 28 comments 0 reactions 0 assignees View on GitHub
documentation topic:editor topic:physics
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.

![image](https://github.com/godotengine/godot/assets/392218/ec4674e5-adf2-4f5c-9843-0ee827282048)

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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.