Newer
Older
TheVengeance-Project-IADE-Unity2D / Assets / Scripts / NPC / Pathfinding / Agent.cs
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;

public class Agent : MonoBehaviour
{
    public Transform target;
    public float speed = 20f;
    public float turnSpeed = 3f;
    public float turnDistance = 2f;
    public float stoppingDistance = 10f;

    public const float pathRequestUpdateTime = 0.2f;
    public const float pathUpdateMoveThreshold = 0.5f;

    private Path path;
    [SerializeField] private bool stop;
    [SerializeField] private Vector2 agentDestination;
    [SerializeField] private Vector2 moveDirection;
    public bool agentStop { get => stop; set => stop = value; }
    public Vector2 agentVelocity => moveDirection;

    private void Awake()
    {
        agentDestination = Vector2.zero;
        stop = false;
    }

    private void Start()
    {
        StartCoroutine(UpdatePath());
    }

    public void OnPathFound(Vector2[] waypoints, bool pathSuccessfull)
    {
        if (pathSuccessfull)
        {
            Debug.Log($"WAYPOINTS: {waypoints.Length}");
            path = new Path(waypoints, transform.position, turnDistance, stoppingDistance);
            StopCoroutine("FollowPath");
            StartCoroutine("FollowPath");
        }
    }


    private IEnumerator UpdatePath()
    {
        while (true)
        {
            Debug.Log("LET ME RUN!");
            if (agentDestination != Vector2.zero)
            {
                if (Time.timeSinceLevelLoad < 0.3f)
                {
                    yield return new WaitForSeconds(.3f);
                }
                PathRequestManager.RequestPath(new PathRequest(transform.position, agentDestination, OnPathFound));

                float sqrMoveThreshold = pathUpdateMoveThreshold * pathUpdateMoveThreshold;
                Vector2 destinationOldPos = agentDestination;

                while (agentDestination != Vector2.zero)
                {
                    yield return new WaitForSeconds(pathRequestUpdateTime);

                    if ((agentDestination - destinationOldPos).sqrMagnitude > sqrMoveThreshold)
                    {
                        PathRequestManager.RequestPath(new PathRequest(transform.position, agentDestination, OnPathFound));
                        destinationOldPos = agentDestination;
                    }
                }
            }

            // Wait for a short time before checking the destination again
            yield return new WaitForSeconds(0.2f);
        }
    }

    private IEnumerator FollowPath()
    {
        bool followingPath = true;
        int pathIndex = 0;
        moveDirection = Vector2.zero;

        float speedPercent = 1f;

        while (followingPath)
        {
            if (stop)
            {
                yield return null;
                continue;
            }

            Vector2 position = new Vector2(transform.position.x, transform.position.y);
            while (path.turnBoundaries[pathIndex].HasCrossedLine(position))
            {
                if (pathIndex == path.finishLineIndex)
                {
                    followingPath = false;
                    break;
                }
                else
                    pathIndex++;

            }

            if (followingPath)
            {
                if (pathIndex >= path.slowDownIndex && stoppingDistance > 0)
                {
                    speedPercent = Mathf.Clamp01(path.turnBoundaries[path.finishLineIndex].DistanceFromPoint(position) / stoppingDistance);

                    if (speedPercent < 0.01f)
                    {
                        followingPath = false;
                    }
                }

                Vector2 targetDirection = (path.lookPoints[pathIndex] - position).normalized;
                moveDirection = Vector2.Lerp(moveDirection, targetDirection, Time.deltaTime * turnSpeed).normalized;
                position += moveDirection * speed * speedPercent * Time.deltaTime;

                transform.position = new Vector3(position.x, position.y, transform.position.z);

            }

            yield return null;
        }
    }

    public void SetDestination(Vector2 newDestination) => agentDestination = newDestination;

    private void OnDrawGizmos()
    {
        if (path != null)
        {
            path.DrawWithGizmos();
        }
    }
}