How To Find The Closest Transform In A Transform Array

Here is my code. I’m feeling weird today and can’t figure it out…I’m really jittery and my brain is all over the place. Blah blah blah, Anyways I’ve got to figure this out. Gotta deadline :slight_smile: Here’s my code:

var targets : Transform[];
var player : Transform;

private var closestTarget : Transform;

function Update ()
{
    closestTarget = targets[SmallestArrayValue(GetDistances(player, targets))];
    Debug.DrawRay(player.position, (closestTarget.position - player.position), Color.green);
}

function SmallestArrayValue (values : float[]) : int
{
    var min : float = values[0];
    var arrayPlace : int;
    for(var i = 1; i < values.Length; i++)
    {
        if(values[i] < min)
        {
            arrayPlace = values[i];
        }
    }
    return values[arrayPlace];
}
function GetDistances (distance : float[], position : Transform, positions : Transform[]) : float[]
{
    for(var trans : Transform in positions)
    {
        distance[trans] = Vector3.Distance(position.position, trans.position);
    }
}

Ever checked out sorting algorithms? Sorting algorithm - Wikipedia
Selection and Insertion are the easier ones. (Not the best efficiently but probably good enough)

If your feeling crazier you can probably do a linq/lambda sort using distance as the sort comparer.

Instead of getting a list of distances you could just check each distance from that specific transform to your target.

– Checking your post again. Sounds like you only care about the closest?

function GetClosest () : Transform
{
    var closestTarget : Transform = null;
    // Set the initial closest distance really high. We don't want to return null.
    var closestDistance: float = 1000;

    for(var trans : Transform in targets)
    {
        var distanceFromTarget = Vector3.Distance(position.position, trans.position);
        if(distanceFromTarget < closestDistance)
        {
            //We have a new closest target.
            closestTarget = trans;
            closestDistance = distanceFromTarget;
        }
    }

    return closestTarget;
}

No need to pass in a bunch of parameters since you have variables that are accessible in your scope. Unless you are making it a helper like function.

thanks, I’ll let you know how it goes :slight_smile:

Ok so this is what I got (getting null ref error on the debug line):

var targets : Transform[];
var player : Transform;

private var closestTarget : Transform;

function Update ()
{
    GetClosest();
    Debug.DrawRay(player.position, (closestTarget.position - player.position), Color.green);
}

function GetClosest () : Transform
{
    var closestTarget : Transform = null;
    var closestDistance : float = Mathf.Infinity;
    for(var trans : Transform in targets)
    {
        var distanceFromTarget = Vector3.Distance(player.position, trans.position);
        if(distanceFromTarget < closestDistance)
        {
            closestTarget = trans;
            closestDistance = distanceFromTarget;
        }
    }
    return closestTarget;
}

Does your array of Targets have any transforms before you run?

You can stop any null ref by do a null reference check. Also you forgot to get the Transform back from the Method. Since it returns a Transform.

You might want to change the name of the variable in the Method/Function to something else since your class variable is the same name. I just wrote it like that because I typed it up in Sublime.

function Update ()
{
    // Lets not check each frame.. Lets do it only on button press c.
    if(Input.GetKeyDown(KeyCode.C))
    {
        closestTarget = GetClosest();
    }

    if(closestTarget != null)
    {
        Debug.DrawRay(player.position, (closestTarget.position - player.position), Color.green);
    }
}

Ok, so it works now…For the first target. When I get that target, it gives me a null ref again.Di i need to remove the target from the array when it is destroyed(the targets are pickups). If so, how? Her’s my code, and thanks for the continued help:

var targets : Transform[];
var player : Transform;

private var closestTarget : Transform;

function Update ()
{
    closestTarget = GetClosest();
    Debug.Log(closestTarget);
    if(closestTarget != null)
    {
        Debug.DrawRay(player.position, (closestTarget.position - player.position), Color.green);
    }
    else if(closestTarget == null)
    {
        closestTarget = GetClosest();
    }
}

function GetClosest () : Transform
{
    var closestTarget : Transform = null;
    var closestDistance : float = Mathf.Infinity;
    for(var trans : Transform in targets)
    {
        var distanceFromTarget = Vector3.Distance(player.position, trans.position);
        if(distanceFromTarget < closestDistance)
        {
            closestTarget = trans;
            closestDistance = distanceFromTarget;
        }
    }
    return closestTarget;
}

I figured it out. I the for loop If threw everything in if(trans != null)

var targets : Transform[];
var player : Transform;

private var closestTarget : Transform;

function Update ()
{
    closestTarget = GetClosest();
    Debug.Log(closestTarget);
    if(closestTarget != null)
    {
        Debug.DrawRay(player.position, (closestTarget.position - player.position), Color.green);
    }
    else if(closestTarget == null)
    {
        closestTarget = GetClosest();
    }
}

function GetClosest () : Transform
{
    var closestTarget : Transform = null;
    var closestDistance : float = Mathf.Infinity;
    for(var trans : Transform in targets)
    {
        if(trans != null)
        {
            var distanceFromTarget = Vector3.Distance(player.position, trans.position);
            if(distanceFromTarget < closestDistance)
            {
                closestTarget = trans;
                closestDistance = distanceFromTarget;
            }
        }
    }
    return closestTarget;
}