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
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Problem with AI that flee away

Discussion in 'Scripting' started by gk104, May 9, 2017.

  1. gk104

    gk104

    Joined:
    Apr 25, 2014
    Posts:
    57
    Currently I'm working on AI enemies in my project and I ran into a problem that I can't solve,
    In the following script, I made the AI run after the player if he see's him, or he gets hit by the player,

    problem is that the enemy runs away from me, I run towards the enemy and he flees back, the AI enemy can't be in a distance less then 12 units from me. dunno what I made wrong, but it's kinda weird.

    Code (CSharp):
    1.     void Update () {
    2.  
    3.         rb.velocity = Vector3.ClampMagnitude(rb.velocity, maxSpeed);    
    4.         float Distance = Vector2.Distance(transform.position, player.position);
    5.  
    6.         HealthText();
    7.  
    8.         if (!Health.isDead() && (HaveSeenPlayer() || gotHit))
    9.         {
    10.             if (Distance > 4f)
    11.             {
    12.                 MoveTowardsPlayer();
    13.             }
    14.             else
    15.                 Attack();
    16.         }
    17.         else
    18.             EnemyCalmState();
    19.     }
    20.  
    21.     bool HaveSeenPlayer()
    22.     {
    23.         Vector2 newPos2D = new Vector2(transform.position.x + Offset(), transform.position.y);
    24.         RaycastHit2D hit = Physics2D.Raycast(newPos2D, Direction(), 4);
    25.  
    26.         if (hit.collider != null && hit.transform.name == "Player")
    27.             return true;
    28.  
    29.         return false;
    30.  
    31.     }
     
    Last edited: May 9, 2017
  2. johne5

    johne5

    Joined:
    Dec 4, 2011
    Posts:
    1,133
    we need to see the MoveTowardsPlayer() function, or you script is reverting to the EnemyCalmState, and that might be move away from player

    my code notes
    Code (CSharp):
    1.         if (!Health.isDead() && (HaveSeenPlayer() || gotHit))
    2.         {
    3.             if (Distance > 4f) // if the player is to far away then move closer
    4.             {
    5.                 MoveTowardsPlayer(); // move closer
    6.             }else
    7.             {
    8.                 Attack(); // i'm close enough so attach the player
    9.             }
    10.         }else //i'm dead, or i have not seen the player or have not gotten hit by the player
    11.         {
    12.             EnemyCalmState();  // do the calm state, ie, idle, patrol....
    13.         }
     
    Last edited: May 9, 2017
  3. gk104

    gk104

    Joined:
    Apr 25, 2014
    Posts:
    57
    Code (CSharp):
    1.    void MoveTowardsPlayer()
    2.     {
    3.             rb.AddForce(player.position * enemyWalkSpeed);
    4.             ChangeEnemyDirection();
    5.  
    6.            EnemyAnimationController.Walk();      
    7.     }
    Code (CSharp):
    1.     void EnemyCalmState()
    2.     {
    3.         Vector2 newPosToWalk = new Vector2(newXPos, transform.position.y); // Vector for the new position
    4.  
    5.         if (!newPositionOnce) {
    6.             newXPos = Random.Range(SpawnedPosOnXaxis - 5, SpawnedPosOnXaxis + 5);
    7.             newPositionOnce = true;
    8.         } // A random point that the enemy can go to
    9.  
    10.         if ((int)transform.position.x != (int)newXPos) // if the enemy hasn't reached the new position yet
    11.         {
    12.             rb.AddForce((newPosToWalk - (Vector2)transform.position) * enemyWalkSpeed);
    13.  
    14.             EnemyAnimationController.Walk();
    15.             ChangeEnemyDirection(newXPos);
    16.         }
    17.         else // if the enemy has reached the new position, it will rest 2 seconds, and then timer will reset, and also one time bool will renabled for a new X position.
    18.         {
    19.             EnemyAnimationController.Idle();
    20.             Timer += Time.deltaTime;
    21.  
    22.             if (Timer > 2)
    23.             {
    24.                 newPositionOnce = false;
    25.                 Timer = 0;
    26.             }
    27.         }
    28.  
    29.     }
     
  4. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    my 2 cents while someone else is helping you:
    If you need only compare a distance as < or > , instead of Distance, you can use (target.position - transform.position).sqrMagnitude
    then check if that value is less than or greater than your checkedDistance * checkedDistance
     
  5. gk104

    gk104

    Joined:
    Apr 25, 2014
    Posts:
    57
    I lack of knowledge in Math/Physics, should I always substract 2 vectors in order to get the new position vector?

    Code (CSharp):
    1.     void MoveTowardsPlayer()
    2.     {
    3.         rb.AddForce((player.position - transform.position) * enemyWalkSpeed);
    4.         ChangeEnemyDirection();
    5.  
    6.          EnemyAnimationController.Walk();    
    7.     }
     
  6. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    I was referring to this more specifically:
    Code (csharp):
    1.  
    2. float Distance = Vector2.Distance(transform.position, player.position);
    3.  
    which could be:
    Code (csharp):
    1.  
    2. float Distance = (transform.position - player.position).sqrMagnitude;
    3. // later, if you wanted to check > 4
    4. if(Distance > (4 * 4)) { // etc
    5.  
    This avoids a square root calculation, if you don't need the precise distance. It's just a performance tweak.