Can anyone help me with a PhysicsServer3D thing?
I am trying to make an area via PhysicsServer3D and then test for intersection with a shape in that area.
I can’t get anything to work
Here’s a very small project to see what I mean. It’s Godot v4.3.dev2.official (The latest from the website)
Here’s my basic gdscript:
@tool
extends Node3D
## Area intersection isue
##
## Trying to make an area by PhysicsServer3D and
## test for intersection with a box shape
##
## Open the scene and press the bool Tog in the inspector
## Observe the printed output.
var A:RID
var state:PhysicsDirectSpaceState3D
@export var tog:bool:
set(b):
tog = false
create()
go()
func create():
print()
print("*****************************")
# Not sure which "space state" to use. Neither seem to work
#state = owner.get_world_3d().direct_space_state
state = self.get_world_3d().direct_space_state
# Make the area
PhysicsServer3D.free_rid(A)
A = PhysicsServer3D.area_create()
PhysicsServer3D.area_set_space(A, state)
PhysicsServer3D.area_set_transform(A, self.transform)
# Debug prints
var areas_transform = PhysicsServer3D.area_get_transform(A)
print("area's transform:", areas_transform)
print("mine :", self.transform)
#mystery command. No clue. It feels like add_child, but who knows?
PhysicsServer3D.area_attach_object_instance_id(A,self.get_instance_id())
#Seems to make no difference
PhysicsServer3D.area_set_monitorable(A, true)
# Also makes no diff
PhysicsServer3D.area_set_ray_pickable(A, true)
func go():
await probe()
func probe():
PhysicsServer3D.area_clear_shapes(A)
# Loop through those mesh instances.
# Test for an intersection with an area.
# If no hit, add that shape to the area.
# This should test, add, test, add etc.
# Until the last mesh called 'overlapper' which is
# plonk on top of the first three. It should report
# an intersection with the area.
# It does not :(
for b:MeshInstance3D in get_children():
# make a shape, the same size as b
var shape_rid = PhysicsServer3D.box_shape_create()
PhysicsServer3D.shape_set_data(shape_rid, b.mesh.size)
#As per docs
var params:PhysicsShapeQueryParameters3D = PhysicsShapeQueryParameters3D.new()
params.shape_rid = shape_rid
params.transform = b.transform
params.collide_with_bodies = false
params.collide_with_areas = true # <-- surely?
# Execute physics queries here...
var surrounds = state.intersect_shape(params,16)
# Debug output
print()
print("Made shape on:", b.name)
print(" orig pos, size:", b.position, " ", b.mesh.size)
print(" shape pos, size:",
params.transform.origin,
PhysicsServer3D.shape_get_data(shape_rid)
)
print("--hits?--")
print(str(surrounds).replace("}, {", "\n"))
# If we did not hit anything, place a shape into the area
# for the next round
if surrounds.is_empty():
var newt:Transform3D = params.transform
PhysicsServer3D.area_add_shape(A, shape_rid, newt)
print(" set as:", newt)
#actually hoping I don't need this await at all.
await get_tree().process_frame
print()
print("Number of shapes:", PhysicsServer3D.area_get_shape_count(A))
for s in range(0,PhysicsServer3D.area_get_shape_count(A)):
var st = PhysicsServer3D.area_get_shape_transform(A,s)
print(" :", st)
In my scene, I placed a few MeshInstance3D nodes (with a box shape resource in each) and the last one overlaps the first three.
In the code, when you press the “Tog” boolean in the inspector, it:
- Makes an area using PhysicsServer3D
- Loops the MeshInstances and creates a shape of the same size and position. (I hope)
- Performs an intersect_shape query with that shape
- If there is no hit/result, then add that shape to the area so that it can be potentially hit the next time round.
I expect the last test to report a collision/intersection because it’s placed to hit three other shapes (previously placed in the loop).
However, I can’t get any results and I am losing hope!