0
\$\begingroup\$

I am working on kart racing game. I have created a series of respawn points (Node3Ds) for when a player falls off of the track. Currently, I am trying to get the closest respawn point to the player and place them at this location when they enter a Boundary (Area3D). However, I can't seem to sort the list of respawn points. Below is my code I am using to try sort my points, however when I print my points, they are always printed in order they appear in the tree and I do not get the closest point.

Is there a better way to sort and get the position of the closest Node3D?

@onready var respawn_points: Array[Respawn_Point]

var player_location:Vector3

func _on_body_entered(body: Node3D) -> void:
    if(body.is_in_group("Player")):
        player_location = body.position         
        var sorted_respawn_points = sortNodesByDistance(respawn_points)
        for point in sorted_respawn_points:
            print(point)
        player.position = sorted_respawn_points[0].position

#Sort Respawn Points by distance
func sortNodesByDistance(nodes: Array) -> Array:
    nodes.sort_custom(compareDistance)
    return nodes

func compareDistance(a: Node3D, b: Node3D) -> int:
    var distance_a = a.position.distance_to(player_location)
    var distance_b = b.position.distance_to(player_location)
    if distance_a < distance_b:
        return -1
    elif distance_a > distance_b:
        return 1
    else:
        return 0
\$\endgroup\$
2
  • 3
    \$\begingroup\$ Note that you don't need to sort the whole array (which takes O(n log n) time in general) just to extract the closest item (which you can do in O(n) time). You don't really care about the exact ranking of the second, third, fourth closest, so you're trying to do more work than required. \$\endgroup\$
    – DMGregory
    Feb 8 at 12:30
  • \$\begingroup\$ My only guess is that you need to use global_position instead of position. With that said, I agree with the above comment and the answer you got: unless you need the sorted array for something else, you are probably better off by iterating over the array and getting the nearest node that way, instead of sorting the array first. \$\endgroup\$
    – Theraot
    Feb 8 at 20:17

1 Answer 1

2
\$\begingroup\$

Here's a version that finds the node closest to a given position, without sorting the whole array, calculating any distance more than once, or using any square roots, so it should be substantially faster than the sorting approach.

I don't work in GDScript often, so I may have made small syntax errors, but the general idea of iterating over the array, keeping track of the closest option you've found so far, should be clear:

func findClosestNode(nodes: Array, position: Vector3D) -> Node3D:
    var closestSquaredDistance = INF
    var closestNode = null
    for node in nodes:
        var squaredDistance = node.global_position.distance_squared_to(position)
        if squaredDistance < closestSquaredDistance:
            closestSquaredDistance = squaredDistance
            closestNode = node

    return node
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .