Search code examples
c#unity-game-enginepath-finding

How Do I avoid objects while following a random path? Unity 2d


I have an enemy object set up to move toward random nodes in a 2d maze environment. The only issue I'm having is keeping the enemy from squeezing through collision walls like a Roach. Here is the code I followed along from a tutorial to move the enemy around with the way points. All help is appreciated, its been almost a week now since I've been trying to wrap my head around this!

    public class Enemy_AI : MonoBehaviour {

     public float speed;
     public float waitTime;
     public float startWaitTime;

     public Transform[] moveSpots;
     private int randomSpot;

     private void Start()
     {
         randomSpot = Random.Range(0, moveSpots.Length);
         waitTime = startWaitTime;
     }

     void Update()
     {
         transform.position = Vector2.MoveTowards(transform.position, moveSpots[randomSpot].position, speed * Time.deltaTime);

         if(Vector2.Distance(transform.position, moveSpots[randomSpot].position) < 0.2f)
         {
             if(waitTime <= 0)
             {
                 randomSpot = Random.Range(0, moveSpots.Length);
                 waitTime = startWaitTime;
             }

             else
             {
                 waitTime -= Time.deltaTime;
             }

         }

     }

 }

enter image description here

enter image description here

enter image description here


Solution

  • for this you should use Raycast, a raycast can detect if there is a object between a given position and a direction, you can also pass the lenght of the ray and which object layers should be considered.

    Having in mind that your code could be something like the following:

    public LayerMask mask;
     void Update()
     {
    
         RaycastHit2D hit = Physics2D.Raycast(transform.position, moveSpots[randomSpot].position, 0.2f, mask);
         if(!hit)
         {
            transform.position = Vector2.MoveTowards(transform.position, moveSpots[randomSpot].position, speed * Time.deltaTime);
    
         }
         if(Vector2.Distance(transform.position, moveSpots[randomSpot].position) < 0.2f)
         {
             if(waitTime <= 0)
             {
                 randomSpot = Random.Range(0, moveSpots.Length);
                 waitTime = startWaitTime;
             }
    
             else
             {
                 waitTime -= Time.deltaTime;
             }
    
         }   
        }
    

    With the mask in the inspector you can select the elements that will be used as collisions in the ray, so your "Obstacles" should be marked there (and have their own layers)

    For debugging if there is any place to move you can do something like this:

    if(Vector2.Distance(transform.position, moveSpots[randomSpot].position) < 0.2f)
    {
    // as it is
    }
    else
    {
        bool canMove = false;
        for(int i = 0; i < moveSpots.Lenght;i++)
        {
           if(Vector2.Distance(transform.position, moveSpots[i].position) < 0.2f)
           {
               canMove = true;
           }
        }
        Debug.Log("Is avaliable any move?" + canMove);
    }