Support Forum

Path is being calculated, but object won't follow path

I’ve been trying to make an enemy ai that follows the player when in view using a circlecast or wander around when the player is not in view. I managed to get the enemy to create a path (i can see it in the scene view), but the object never actually moves towards the player.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Pathfinding;

public class EnemyAI : MonoBehaviour
{
    Transform target;

    public float viewDistance = 7f; //length of CircleCast
    public float circleThickness = 6f; //thickness of CircleCast

    public float enemyMoveSpeed = 1f; //self-explanatory
    public float nextWaypointDistance = 1f; //distance until enemy moves to next waypoint
    public float distanceFromPlayer = 7f; //check if player is within this range
    public float attackDistance = 0.1f;

    public float repathRate = 0.5f;
    private float lastRepath = float.NegativeInfinity;

    Path path;
    IAstarAI ai;
    int currentWaypoint = 0;

    Seeker seeker;
    Rigidbody2D rBody;

    bool isFollowing; //bool to check if CircleCast hits player
    public bool isAttacking;

    //patrol stuff
    public float patrolRadius = 8f;


    private void Start()
    {
        isFollowing = false;

        Physics2D.queriesStartInColliders = false; //ensures that enemy doesn't detect itself

        seeker = GetComponent<Seeker>();
        //rBody = GetComponent<Rigidbody2D>();

        target = GameObject.FindGameObjectWithTag("Player").transform; //makes the target any object with "Player" tag
    }

    private void Update()
    {
        if (Vector2.Distance(transform.position,
                                target.position) <= distanceFromPlayer) //check if player is within range of enemy
        {
            RaycastHit2D hitInfo = Physics2D.CircleCast(transform.position,
                                  circleThickness, transform.up, viewDistance); //create CircleCast

            if (hitInfo.collider != null)
            {
                if (hitInfo.collider.CompareTag("Player")) //check if CircleCast hits player
                {
                    if (hitInfo.distance < attackDistance) //check if player is within attack distance
                    {
                        Debug.Log("Player is within attack distance");
                        target.GetComponent<PlayerMovement>().enabled = false; //disable player movement
                    }                                                        //when player is close to enemy

                    isFollowing = true;

                    Debug.Log("Player Detected");
                    
                    isFollowing = false;
                }
            }
        }
    }

    private void FixedUpdate()
    {  
        if (isFollowing == false)
        {
            //pathfinding stuff
            if (Time.time > lastRepath + repathRate && seeker.IsDone())
            {
                lastRepath = Time.time;
                seeker.StartPath(transform.position, PickPointInCircle(), OnPathComplete);
            }

            if (path == null)
            {
                // We have no path to follow yet, so don't do anything
                return;
            }

            if (currentWaypoint > path.vectorPath.Count)
            {
                return;
            }

            if (currentWaypoint == path.vectorPath.Count)
            {
                currentWaypoint++;
                return;
            }
            //pathfinding stuff end
        }

        if (isFollowing == true)
        {
            //pathfinding stuff
            if (Time.time > lastRepath + repathRate && seeker.IsDone())
            {
                lastRepath = Time.time;
                seeker.StartPath(transform.position, target.position, OnPathComplete);
            }

            if (path == null)
            {
                // We have no path to follow yet, so don't do anything
                return;
            }

            if (currentWaypoint > path.vectorPath.Count)
            {
                return;
            }

            if (currentWaypoint == path.vectorPath.Count)
            {
                Debug.Log("End Of Path Reached");
                currentWaypoint++;
                return;
            }
            //pathfinding stuff end  
        }
            Vector2 dir = (path.vectorPath[currentWaypoint] - transform.position).normalized;
            rBody.MovePosition(dir * enemyMoveSpeed * Time.deltaTime);
    }

    void OnPathComplete(Path p)
    {
        if (!p.error)
        {
            path = p;
            currentWaypoint = 0;
        }

        else
        {
            return;
        }   
    }

    Vector2 PickPointInCircle()
    {
        Vector3 point = Random.insideUnitCircle * patrolRadius;

        point.y = 0;
        point.z = 0;
        point += transform.position;
        return point;
    }

    void FollowPath()
    {
        rBody.MovePosition(target.position * enemyMoveSpeed * Time.deltaTime);
    }
}

I hope that code is readable, as I’m very new to unity and c#, and any help would be appreciated.

Hi

I’m not sure. That’s quite a long script to debug just by reading it.
If you are new to C# I would recommend using one of the built-in movement scripts such as AIPath.

Kind of a late reply, but would it help if I condensed the code?

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Pathfinding;

public class EnemyAI : MonoBehaviour
{
    Transform target;

    public float enemyMoveSpeed = 1f; //self-explanatory
    public float nextWaypointDistance = 1f; //distance until enemy moves to next waypoint 

    public float repathRate = 0.5f;
    private float lastRepath = float.NegativeInfinity;

    Path path;
    int currentWaypoint = 0;

    Seeker seeker;
    Rigidbody2D rBody;

    bool isFollowing; //bool to check if CircleCast hits player

    private void Start()
    {
        isFollowing = false;

        seeker = GetComponent<Seeker>();
        rBody = GetComponent<Rigidbody2D>();
    }

    private void FixedUpdate()
    {  
        if (isFollowing == false)
        {
            //pathfinding stuff
            if (Time.time > lastRepath + repathRate && seeker.IsDone())
            {
                lastRepath = Time.time;
                seeker.StartPath(transform.position, PickPointInCircle(), OnPathComplete);
            }

            if (path == null)
            {
                return;
            }

            if (currentWaypoint > path.vectorPath.Count)
            {
                return;
            }

            if (currentWaypoint == path.vectorPath.Count)
            {
                currentWaypoint++;
                return;
            }
            //pathfinding stuff end
        }

        Vector2 dir = (path.vectorPath[currentWaypoint] - transform.position).normalized;        
        rBody.MovePosition(dir * enemyMoveSpeed * Time.deltaTime);

        float distance = Vector2.Distance(rBody.position, path.vectorPath[currentWaypoint]);

        if (distance < nextWaypointDistance)
        {
            currentWaypoint++;
        }
    }

    void OnPathComplete(Path p)
    {
        if (!p.error)
        {
            path = p;
            currentWaypoint = 0;
        }

        else
        {
            return;
        }   
    }

    Vector2 PickPointInCircle()
    {
        Vector3 point = Random.insideUnitCircle * patrolRadius;

        point.z = 0;
        point += transform.position;
        return point;
    }
}

This is the code I have to generate a random point in a circle and have the object follow it. The thing is, when I start the game window, a path is generated (I can see in the scene view) but the object is constantly teleported to the origin. Also, in the console, a path is generated every frame, although I don’t know if that is related to my issue. Any advice would be helpful, thanks.

Note that RigidBody.MovePosition moves the rigidbody to a given point, not in a particular direction. Right now you are feeding it a direction.

See https://docs.unity3d.com/ScriptReference/Rigidbody.MovePosition.html