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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

How to make my character choose the closest object in range?

Discussion in 'Scripting' started by GuyStreamsStuff, Nov 22, 2018.

  1. GuyStreamsStuff

    GuyStreamsStuff

    Joined:
    Dec 22, 2017
    Posts:
    27
    So I'm making a Sonic fangame and when pressing the Y button, i need to make sonic go through a series of rings. Everything works perfectly except for the fact that on button press Sonic goes to the furthest ring in range.
    I tried adding some code I found to sort lists but it seems like it doesn't do much. Would you be so kind as to take a look at this snippet of code and telling me what I'm doing wrong? Thanks!
    Code (CSharp):
    1.  foreach (var ringy in rings)
    2.             {
    3.                 if (ringy != null)
    4.                 {
    5.                     if ((this.transform.position - ringy.transform.position).magnitude < lighDashDistance)
    6.                     {
    7.                         directionToRing = ringy.transform.position - transform.position;
    8.                         float dSqrToRingy = directionToRing.sqrMagnitude;
    9.                         if (Mathf.Infinity > dSqrToRingy)
    10.                         {
    11.                             nearRing = ringy;
    12.                             YButtonDown = false;
    13.  
    14.                             animator.SetBool("isHoming", true);
    15.                             GetComponent<lightDash>().enabled = true;
    16.                             YButtonDown = false;
    17.                             lightDashed = true;
    18.  
    19.                             this.enabled = false;
    20.                             return;
    21.  
    22.                         }
    23.  
    24.  
    25.                     }
    26.                 }
    27.             }
     
  2. Lelefant

    Lelefant

    Joined:
    Jul 1, 2015
    Posts:
    22
    This doesn't look like it's performing any sorting, are you sure that you implemented the correct snippet?

    Usually, to sort the rings and do something with the nearest ring, you would go through the whole list, keeping track of the currently closest ring and performing actions afterward:

    Code (CSharp):
    1. Ring nearestRing = null;
    2. float minRingDistance = Mathf.Infinity;
    3.  
    4. // Find the nearest ring
    5. foreach (var ringy in rings)
    6. {
    7.     float currentDistance = (ringy.transform.position - transform.position).magnitude;
    8.     // Check if this ring is nearer that the previously nearest ring
    9.     if (currentDistance < minRingDistance && currentDistance <= lightDashDistance)
    10.     {
    11.         nearestRing = ringy;
    12.         minRingDistance = currentDistance;
    13.     }
    14. }
    15.  
    16. if (nearestRing != null)
    17. {
    18.     // Do something
    19. }
     
  3. Nickromancer

    Nickromancer

    Joined:
    Jul 31, 2016
    Posts:
    92
    note that if you are just comparing distance you may want to use Vector3.sqrMagnitude instead of Vector3.magnitude which is faster. It will be more obvious when dealing with more objects and do it frequently.
     
    Lelefant likes this.
  4. GuyStreamsStuff

    GuyStreamsStuff

    Joined:
    Dec 22, 2017
    Posts:
    27
    So I wrote this but it's still targeting the furthest ring in range. And the movement part of the script doesn't even work anymore (it uses pretty much the same system, but in Update instead of on button press. Also if I pick up a ring and press the button, I'm stuck in place and can't move and it gives me an error in the console
    This is the error: "Missing Reference Exception: The object of type 'GameObject' has been destroyed but you are still trying to access it.
    Your script should either check if it is null or you should not destroy the object."


    Here's the code that you suggested:
    Code (CSharp):
    1.             foreach (var ringy in rings)
    2.             {
    3.  
    4.                 float currentDistance = (ringy.transform.position - transform.position).magnitude;
    5.  
    6.  
    7.        
    8.  
    9.                 if (currentDistance < minRingDistance && currentDistance <= lighDashDistance)
    10.                 {
    11.                     nearRing = ringy;
    12.                     YButtonDown = false;
    13.  
    14.                     animator.SetBool("isHoming", true);
    15.                     GetComponent<lightDash>().enabled = true;
    16.                     YButtonDown = false;
    17.                     lightDashed = true;
    18.  
    19.                     this.enabled = false;
    20.                     return;
    21.                 }
    22.  
    23.                 else
    24.                 {
    25.                     nearRing = null;
    26.                 }
    27.  
    28.  
    29.  
    30.            }
    31.  
     
  5. GuyStreamsStuff

    GuyStreamsStuff

    Joined:
    Dec 22, 2017
    Posts:
    27
    My bad, erased on accident the check for nul. duh. So it still picks the furthest ring in range and after picking up a single ring, the action stops instead of going for the next one. Going to try and figure out what's happening.

    EDIT: sorted it out, but again, this code does exactly the same thing (albeit cleaner, that's for sure)
    that the old code.
     
    Last edited: Nov 22, 2018
  6. TheFunnySide

    TheFunnySide

    Joined:
    Nov 17, 2018
    Posts:
    192

    This saves the closest ring in nearRing or Null if there is no ring.
     
  7. GuyStreamsStuff

    GuyStreamsStuff

    Joined:
    Dec 22, 2017
    Posts:
    27
    Do I have to reset the
    float shortestDistance
    for every activation of the script?
     
  8. TheFunnySide

    TheFunnySide

    Joined:
    Nov 17, 2018
    Posts:
    192
    Code (CSharp):
    1.  
    2. public ring getClosestRingWithinXDistance (List<ring>rings ,float minRingDistance)
    3. {
    4.     float shortestDistance=99999999;
    5.     float currentDistance;
    6.     ring nearRing;
    7.             foreach (var ringy in rings)
    8.                 {
    9.  
    10.                      currentDistance = (ringy.transform.position - transform.position).magnitude;
    11.  
    12.  
    13.      
    14.  
    15.                     if (currentDistance < minRingDistance && currentDistance <= shortestDistance)
    16.                     {
    17.                         shortestDistance = currentDistance;
    18.                         nearRing = ringy;
    19.                     }
    20.                   }
    21. return nearRing;
    22. }
    23.