Hello everyone ! I am looking for the simplest way to know which is the 3D object closest to an object. Is there a simple method to do it? thank you !
get the nearest object
I don't think there's a nice easy way to do that. The most obvious way I can think of is to use a spherical area of the smallest size that will get the job done, call get_overlapping_bodies(), and loop through the resulting array of objects, checking the distances to them to find the nearest one.
- Edited
(as an opportunity to test markdown on this forum) Here is the "simplest" method I'd use :
var A = get_node("main_object");
var min_distance = 99999999.0;
var closest_object = null;
for B in get_children() : #{
if B == A : continue;
var dist = A.get_global_transform().origin.distance_to( B.get_global_transform().origin );
if dist < min_distance : min_distance = dist; closest_object = B;
#}
Thanks Ross and yoann ! Ross : it's a good idea indeed, I keep in mind, just in case;) Yoann : a simple and brilliant script that I like! Thank you, it works perfectly! (There is a small mistake, this is not "dist = min_distance" but "min_distance = dist";))
The area idea is a way to optimize it. Depending on the exact situation of course, get_children() might be better or worse. Looping through every single object in your scene could have a serious performance impact.
- Edited
@Ross said: The area idea is a way to optimize it. Depending on the exact situation of course, get_children() might be better or worse. Looping through every single object in your scene could have a serious performance impact.
yes indeed, the two solutions are interesting. In this case, I use a node specially dedicated to the storage of objects to be tested, and I test the proximity only when needed, which reduces the impact on resources :)
I think you can make the "B" objects to include themselves inside a proper array of "nearbyObjects", then you just search for the neaby objects instead of looking for every object.
I'd put all my enemies as children of a single node, and use that type of categorization for every type of object (trees, NPCs, items) then when you need to get the nearest enemy, just loop through the children of their parent node. I'd also add ways to limit the number of each specific object the game spawns.
- Edited
Using groups is how I handle finding things of a certain type. You can do groups like animal, dog, cat and then you can get all the animals or just the dogs or cats. Objects can have any number of groups.
- Edited
This is the easiest and most efficient way that I've found so far:
onready var GrabArea = $Area
#var ClosestObject = null # Optional
func _unhandled_input(_event):
if Input.is_action_just_pressed("ui_accept"):
var AvailableObjects = GrabArea.get_overlapping_bodies()
if !AvailableObjects: return
var Array_ = []
var ArrayPosition: int = -1
Array_.resize(AvailableObjects.size())
for element in AvailableObjects:
var Distance = element.global_transform.origin.distance_to(global_transform.origin)
ArrayPosition += 1
Array_[ArrayPosition] = Distance
for element in AvailableObjects:
var Distance = element.global_transform.origin.distance_to(global_transform.origin)
if Distance == Array_.min():
element.queue_free()
#element = ClosestObject # Optional
Create an Area node in your player scene.
Make sure ONE layer is dedicated to collecting items, otherwise, the Area node will calculate objects not relating to collectable items--it will mess up the code.
Add all collectable items in the layer dedicated to collecting items.
For the Area node, uncheck "Monitorable", uncheck all of its collision layer bits, and select ONLY the layer dedicated to collecting items for its collision mask.