# GM:S 1.4 Difficulties determining the nearest instance in 3D space

Discussion in 'Programming' started by Prometheus1998_, Mar 6, 2019.

Tags:
1. ### Prometheus1998_Member

Joined:
Aug 26, 2018
Posts:
22
I'm trying to create a script that returns the nearest instance in 3-dimensional space, by looping through all active instances of the object, evaluating the distance using the built-in function "point_distance_3d", sorting the ds_grid containing the data so that the smallest distance value is in the [0,1] position, and returning the id saved in the [0,0] position.

Code:
```///instance_nearest_3d(x,y,z,obj)
object = argument3;
arg_x = argument0;
arg_y = argument1;
arg_z = argument2;

var instances = ds_grid_create(instance_number( object ),1);

for(var i = 0; i < instance_number( object ); i += 1) {
var inst = instance_find( object , i);
var dist = point_distance_3d(inst.x,inst.y,inst.z, arg_x , arg_y , arg_z )

}

ds_grid_sort(instances,1,true);

var val = ds_grid_get(instances,0,0);

ds_grid_destroy(instances);

return val;
```

For ease of testing, I've been using a flat plane, assuming all objects are on the same z-level (z = 0).

The grid I have been using to test has nine objects, arranged like so:

| a b c |
| d e f |
| g h i |

The object running the test starts in the "e" position, but indicates the closest object it tests for is in the "i" position. In addition, despite running in the "Step" event, it only calculates the nearest object once. It behaves exactly the same if I change the "ascending" parameter for ds_grid_sort from true to false.

Replacing the script in the spoiler tags above with the built-in function "instance_nearest" functions exactly the way it should, so I'm reasonably confident the problem is in the ds_grid, either saving the data or sorting it. Given the way it (doesn't) change behavior when switching how it sorts the information in the grid, I'm pretty sure I messed up the sorting. I just can't figure out how, and would appreciate any help that can be provided.

2. ### Simon GustMember

Joined:
Nov 15, 2016
Posts:
3,218

Where are the origins placed on these instaces?
Are your arg_x, arg_y, arg_z exactly the x, y and z of the searching instance?

3. ### TheSnidrHeavy metal viking dentistGMC Elder

Joined:
Jun 21, 2016
Posts:
474
If you only need the single nearest instance, it's easier to use "with" and store the nearest instance in a variable:
Code:
```var dist = 99999;
var nearest = - 1;
with object
{
var d = point_distance_3d(stuff);
if (d < dist)
{
dist = d;
nearest = id;
}
}
return nearest;```

4. ### Prometheus1998_Member

Joined:
Aug 26, 2018
Posts:
22
By origins, do you mean the exact x and y value of the object that the sprite is drawn from?
They are procedurally placed, centered on the player object.

The ds_grid's 0 column contains the "id" variable of each object, the 1 column contains the calculated distance.

Arg_x, arg_y, and arg_z are the exact coordinates that the script calculates the distance to. It can be the coordinates of the calling function, or it can be some other coordinate entirely.

Let me know if I understand the concept behind this correctly, please:
First, the code initializes the "dist" variable to an arbitrarily large number that's unlikely to ever come up as a legitimate distance value, and sets the "nearest" variable to -1, which will never be a real id. From there, it executes code in all other instances (looping through by instance number?), calculating the distance between the two points in 3d space. If this distance is shorter than the existing value in the "dist" variable, it sets the "dist" variable to this new value, sets "nearest" to that instance's id, and continues on. The first instance that the code operates through should always overwrite the "dist" and "nearest" variables.
At the end of the "with" construction, the closest instance's id should be stored in the nearest variable. If the "nearest" variable is still -1, there are no valid active instances to be found.

5. ### TheSnidrHeavy metal viking dentistGMC Elder

Joined:
Jun 21, 2016
Posts:
474
Correct you are! On all accounts actually. Good job!