Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

How To Find The Closest Transform In A Transform Array

Discussion in 'Scripting' started by keenanwoodall, Aug 5, 2014.

  1. keenanwoodall

    keenanwoodall

    Joined:
    May 30, 2014
    Posts:
    595
    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 :) Here's my code:
    Code (js):
    1.  
    2. var targets : Transform[];
    3. var player : Transform;
    4.  
    5. private var closestTarget : Transform;
    6.  
    7. function Update ()
    8. {
    9.     closestTarget = targets[SmallestArrayValue(GetDistances(player, targets))];
    10.     Debug.DrawRay(player.position, (closestTarget.position - player.position), Color.green);
    11. }
    12.  
    13. function SmallestArrayValue (values : float[]) : int
    14. {
    15.     var min : float = values[0];
    16.     var arrayPlace : int;
    17.     for(var i = 1; i < values.Length; i++)
    18.     {
    19.         if(values[i] < min)
    20.         {
    21.             arrayPlace = values[i];
    22.         }
    23.     }
    24.     return values[arrayPlace];
    25. }
    26. function GetDistances (distance : float[], position : Transform, positions : Transform[]) : float[]
    27. {
    28.     for(var trans : Transform in positions)
    29.     {
    30.         distance[trans] = Vector3.Distance(position.position, trans.position);
    31.     }
    32. }
     
  2. Ereous

    Ereous

    Joined:
    Aug 29, 2012
    Posts:
    163
    Ever checked out sorting algorithms? http://en.wikipedia.org/wiki/Sorting_algorithm#Selection_sort
    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.
    http://stackoverflow.com/questions/722868/sorting-a-list-using-lambda-linq-to-objects

    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?
    Code (CSharp):
    1. function GetClosest () : Transform
    2. {
    3.     var closestTarget : Transform = null;
    4.     // Set the initial closest distance really high. We don't want to return null.
    5.     var closestDistance: float = 1000;
    6.  
    7.     for(var trans : Transform in targets)
    8.     {
    9.         var distanceFromTarget = Vector3.Distance(position.position, trans.position);
    10.         if(distanceFromTarget < closestDistance)
    11.         {
    12.             //We have a new closest target.
    13.             closestTarget = trans;
    14.             closestDistance = distanceFromTarget;
    15.         }
    16.     }
    17.  
    18.     return closestTarget;
    19. }
    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.
     
    Last edited: Aug 5, 2014
  3. keenanwoodall

    keenanwoodall

    Joined:
    May 30, 2014
    Posts:
    595
    thanks, I'll let you know how it goes :)
     
  4. keenanwoodall

    keenanwoodall

    Joined:
    May 30, 2014
    Posts:
    595
    Ok so this is what I got (getting null ref error on the debug line):
    Code (js):
    1.  
    2. var targets : Transform[];
    3. var player : Transform;
    4.  
    5. private var closestTarget : Transform;
    6.  
    7. function Update ()
    8. {
    9.     GetClosest();
    10.     Debug.DrawRay(player.position, (closestTarget.position - player.position), Color.green);
    11. }
    12.  
    13. function GetClosest () : Transform
    14. {
    15.     var closestTarget : Transform = null;
    16.     var closestDistance : float = Mathf.Infinity;
    17.     for(var trans : Transform in targets)
    18.     {
    19.         var distanceFromTarget = Vector3.Distance(player.position, trans.position);
    20.         if(distanceFromTarget < closestDistance)
    21.         {
    22.             closestTarget = trans;
    23.             closestDistance = distanceFromTarget;
    24.         }
    25.     }
    26.     return closestTarget;
    27. }
     
  5. Ereous

    Ereous

    Joined:
    Aug 29, 2012
    Posts:
    163
    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.

    Code (CSharp):
    1. function Update ()
    2. {
    3.     // Lets not check each frame.. Lets do it only on button press c.
    4.     if(Input.GetKeyDown(KeyCode.C))
    5.     {
    6.         closestTarget = GetClosest();
    7.     }
    8.  
    9.     if(closestTarget != null)
    10.     {
    11.         Debug.DrawRay(player.position, (closestTarget.position - player.position), Color.green);
    12.     }
    13. }
     
  6. keenanwoodall

    keenanwoodall

    Joined:
    May 30, 2014
    Posts:
    595
    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:

    Code (js):
    1.  
    2. var targets : Transform[];
    3. var player : Transform;
    4.  
    5. private var closestTarget : Transform;
    6.  
    7. function Update ()
    8. {
    9.     closestTarget = GetClosest();
    10.     Debug.Log(closestTarget);
    11.     if(closestTarget != null)
    12.     {
    13.         Debug.DrawRay(player.position, (closestTarget.position - player.position), Color.green);
    14.     }
    15.     else if(closestTarget == null)
    16.     {
    17.         closestTarget = GetClosest();
    18.     }
    19. }
    20.  
    21. function GetClosest () : Transform
    22. {
    23.     var closestTarget : Transform = null;
    24.     var closestDistance : float = Mathf.Infinity;
    25.     for(var trans : Transform in targets)
    26.     {
    27.         var distanceFromTarget = Vector3.Distance(player.position, trans.position);
    28.         if(distanceFromTarget < closestDistance)
    29.         {
    30.             closestTarget = trans;
    31.             closestDistance = distanceFromTarget;
    32.         }
    33.     }
    34.     return closestTarget;
    35. }
     
  7. keenanwoodall

    keenanwoodall

    Joined:
    May 30, 2014
    Posts:
    595
    I figured it out. I the for loop If threw everything in if(trans != null)
    Code (js):
    1.  
    2. var targets : Transform[];
    3. var player : Transform;
    4.  
    5. private var closestTarget : Transform;
    6.  
    7. function Update ()
    8. {
    9.     closestTarget = GetClosest();
    10.     Debug.Log(closestTarget);
    11.     if(closestTarget != null)
    12.     {
    13.         Debug.DrawRay(player.position, (closestTarget.position - player.position), Color.green);
    14.     }
    15.     else if(closestTarget == null)
    16.     {
    17.         closestTarget = GetClosest();
    18.     }
    19. }
    20.  
    21. function GetClosest () : Transform
    22. {
    23.     var closestTarget : Transform = null;
    24.     var closestDistance : float = Mathf.Infinity;
    25.     for(var trans : Transform in targets)
    26.     {
    27.         if(trans != null)
    28.         {
    29.             var distanceFromTarget = Vector3.Distance(player.position, trans.position);
    30.             if(distanceFromTarget < closestDistance)
    31.             {
    32.                 closestTarget = trans;
    33.                 closestDistance = distanceFromTarget;
    34.             }
    35.         }
    36.     }
    37.     return closestTarget;
    38. }