Search Unity

Finding the nearest of a certain game object in c#

Discussion in 'Scripting' started by dmakinde, Mar 29, 2013.

  1. dmakinde

    dmakinde

    Joined:
    Mar 9, 2013
    Posts:
    6
    Hi everyone,

    I've hit a bit of a wall with a project I'm working on. Essentially I am trying to make a basic AI for an enemy that retreats to the nearest one of it's kind when it reaches a certain amount of health. I have a theory on how to carry this out but clearly the logic is flawed somewhere... hopefully you guys can help! I have a similar-ish code working in another part of the script. That code simply judges the distance between it and the player and when it within a certain range, it follows.

    The part of the script that handles that aspect is the following:

    Code (csharp):
    1.  
    2. public Transform Player;
    3. public float MaxRange = 15f;
    4. public float MinRange = 1.3f;
    5.  
    6. if((System.Convert.ToBoolean(Vector3.Distance(transform.position,
    7. Player.position)<MaxRange)))
    8. {
    9.     if((System.Convert.ToBoolean(Vector3.Distance(transform.position,
    10.     Player.position)>MinRange)))
    11.     {
    12.         State = demonState.Walking;
    13.     }
    14.     else
    15.     {
    16.         isAttacking = true;
    17.         State = demonState.Attacking;
    18.     }
    19.  
    20.  
    and that works fine, however I am trying to re factor it into a function that loops through all the game objects in the world called demon and then picks one within a certain range to be it's sort of backup. With that variable set I will then create a state where the enemy runs up to it and then does the required commands.Here is what I have attempted so far.
    Code (csharp):
    1.  
    2. public Transform Backup;
    3.  
    4. for (int i = 0; i < 12; i++) // I'm using the number 12 because there are 12 of them in the game at the moment, I don't know the
    5. //expression that encompasses all of a particular object yet... as you can tell, I'm learning this as I go :P
    6. {
    7. if((System.Convert.ToBoolean(Vector3.Distance(transform.position,
    8.         GameObject.Find("demon").transform.position)<MaxRange*2)))
    9.     {
    10.         Backup = GameObject.Find("demon").transform;
    11.         Debug.Log("Backup detected");
    12.     }
    13. }
    14.  
    The funny thing about that code is that when I run it, it shows the debug message but it doesn't set the variable. As I said before, I know the problem lies with me but I'm a little stuck. Any help would be appreciated :)
     
  2. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    One thing, you don't need to use System.Convert.ToBoolean. Expressions such as "Vector3.Distance(x, y) < range" already evaluate to booleans.

    --Eric
     
  3. Kinos141

    Kinos141

    Joined:
    Jun 22, 2011
    Posts:
    969
  4. dmakinde

    dmakinde

    Joined:
    Mar 9, 2013
    Posts:
    6
    wow that link really helped! I managed to adapt the code and it ALMOST works. I suppose now it works a little too well. Basically I applied that code to all the enemies in the level as they all will have the retreating function. Here is the code I used/adapted:

    Code (csharp):
    1.          Vector3 currentPosition = transform.position;
    2.         var currentPos = transform.position;    //Cache it - it's expensive!
    3. var closestGameObject = GameObject.FindGameObjectsWithTag("enemy")
    4.    .Select( go => new { go = go, position  = go.transform.position })
    5.    .Aggregate((current, next)=>
    6.       (current.position - currentPosition).sqrMagnitude <
    7.       (next.position - currentPosition).sqrMagnitude
    8.       ? current : next).go;
    9.         Backup = closestGameObject.transform;
    sorry for the bad formatting, most of it was lifted from that link. The thing is it detects that the nearest object is itself, and thus targets itself, so when I get the retreating script done, it's essentially going to run back to itself.. and that's not particularly helpful >_<. Is there any way for it to take the next closest object instead? Thanks for the help guys. It has definitely pointed me in the right direction!
     
  5. dmakinde

    dmakinde

    Joined:
    Mar 9, 2013
    Posts:
    6
    never mind I've figured it out! My solution was to simply add a new tag into the mix. When the enemy reaches the amount of health necessary to run the above script and find the nearest enemytag, the script will change the current enemy's tag to retreating enemy, so it will target the second nearest enemy :) Kinos141 thanks again for showing me that page :)
     
  6. Themp

    Themp

    Joined:
    Nov 8, 2011
    Posts:
    96
    woah... Are you originally a C++ dev or something? that code looks really compressed to me..
     
    oysterCAKE likes this.