Get all surrounding objects from a specific object

Godot Version

4.2.1

Question

In my game I try to capture all surrounding objects of a certain type from “outside”, i.e. from another object. An example is a police car, which uses its process/update method to record all citizens around it within a certain area.

Back in Unity I would have done something like this:

void Update()
{
    Collider[] citizenCollidersArroundMe = Physics3D.OverlapCircleAll(myPosition, radiusToCheck);
}

Is there a Godot counterpart for this?

You could always of course just attach an Area2D to your object in question and just have a big circle shape collider around it as well.

And then just do a count from there.

1 Like

I already had this thought (just with the Area3D). This works quite well, but I’m worried that it might not be performant enough.

Is it safe to use this method outside of the PhysicProcess() method? The docs say that this may not containt the most “current” collection of bodies and that it is better to work with signals.
I then imagine that I maintain a list of neighbors, one neighbor being added to or one removed each time the Enter or Leaf signals appear. I could then query this list from outside. What do you all mean?

public Godot.Collections.Array<Node3D> GetNeighbors()
{
     return this.neighborArea3D.GetOverlappingBodies();
}

On the other hand, I tried using the “low level” approach that Shrooms suggested. However, this has not yet led to success.
I was trying something like that:

   var shapeRid = PhysicsServer3D.SphereShapeCreate();
   var radius = 20.0f;
   PhysicsServer3D.ShapeSetData(shapeRid, radius);
   var pparams = new PhysicsShapeQueryParameters3D();
   pparams.CollisionMask = 2;
   var directSpaceState = GetWorld3D().DirectSpaceState;
   var result = directSpaceState.IntersectShape(pparams);
1 Like

you at least put in some effort and i appreciate that. after some head scratching i put this together. you’ll have to convert it to c# but i am confident you can take it from here.

extends Node2D

func _process(_a_delta):
	global_position = get_global_mouse_position()

func _physics_process(_a_delta):
	var v_shape_rid = PhysicsServer2D.circle_shape_create()
	PhysicsServer2D.shape_set_data(v_shape_rid, 50)
	
	var v_query = PhysicsShapeQueryParameters2D.new()
	v_query.collide_with_areas = true
	v_query.collide_with_bodies = true
	v_query.shape_rid = v_shape_rid
	
	var v_transform = Transform2D()
	v_transform.origin = global_position
	v_query.transform = v_transform
	
	var v_result = get_world_2d().direct_space_state.intersect_shape(v_query)
	print (v_result)
	
	PhysicsServer2D.free_rid(v_shape_rid)

1 Like

I would think Area2D would be fine performance wise given its the most simple node to detect colliding bodies in Godot.

In effect the collision is an ‘event’ in Godot anyway, so its using a Godot signal already.

For example in an asteroids clone I did (using c#) I just had a Area2D around the spawn area in the middle of the screen so I didnt spawn the player if there was at least one asteroid inside it.

It then just checked the number of colliding bodies with the Area (using has_overlapping_areas() every frame until it was false, and then spawned the player once it was.

Occams Razor.

2 Likes