Untitled

 avatar
unknown
csharp
2 months ago
5.3 kB
8
Indexable
using System.Runtime.CompilerServices;
using NUnit.Framework;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.TestTools;


public class AIBehaviour : MonoBehaviour
{
    private NavMeshAgent agent;
    public Transform target;
    public Transform[] patrolPoints;
    public Transform[] coverPoints;
    private int currentPatrolIndex = 0;
    public float patrolWaitTime = 1f;
    private bool IsPatrolling = false;
    public float chaseRange = 10f;
    public float sightRange = 45f;
    public float stalkRange = 45f;
    public Transform playerCamera;
    private delegate void State();
    private float FieldOfView = 45f;
    private bool IsConcealed = false;
    private enum AIState { Patrolling, Chasing, Stalking }
    private AIState currentState;
    private float distanceToPlayer;
    

    


    void Start()
    {
        agent = GetComponent<NavMeshAgent>();
        currentState = AIState.Patrolling;
        MoveToNextPatrolPoint();
    }

    void Update()
    {

        distanceToPlayer = Vector3.Distance(transform.position, target.position);


        switch (currentState)
        {
            case AIState.Patrolling:
                PatrolState();
                break;
            case AIState.Chasing:
                ChaseState();
                break;
            case AIState.Stalking:
                if (distanceToPlayer <= stalkRange)
                {
                    Debug.Log("Stalking...");
                }
                else
                {
                    PatrolState();
                }
                StalkState();
                break;    
        }
        
        if (currentState == AIState.Stalking)
        {
            CheckIfSeen();
        }

        CheckStateTransitions();
    }

    private void PatrolState()
    {
        if (!agent.pathPending && agent.remainingDistance < 0.5f)
        {
            StartCoroutine(PatrolWait());
        }
    }

    private System.Collections.IEnumerator PatrolWait()
    {
        IsPatrolling = false;
        yield return new WaitForSeconds(patrolWaitTime);
        MoveToNextPatrolPoint();
        IsPatrolling = true;
    }

    private void MoveToNextPatrolPoint()
    {
        if (patrolPoints.Length == 0)
        {
            Debug.Log("No Patrol Points Detected, standing still...");
            return;
        }

        agent.SetDestination(patrolPoints[currentPatrolIndex].position);

        currentPatrolIndex = (currentPatrolIndex + 1) %patrolPoints.Length;
    }

    private void StalkState()
    {
        if (CanSeePlayer())
        {
            Vector3 coverPoint = FindNearestCover();
            MoveToCover(coverPoint);

        }
        else
        {
            if (!IsConcealed)
            {
                IsConcealed = true;
                Vector3 coverPoint = FindNearestCover();
                MoveToCover(coverPoint);

            }
        }
    }

    private bool CanSeePlayer()
    {
        Vector3 directionToPlayer = target.position - transform.position;
        float angle = Vector3.Angle(transform.forward, directionToPlayer);

        if (angle < FieldOfView)
        {
            RaycastHit hit;
            if (Physics.Raycast(transform.position, directionToPlayer.normalized, out hit))
            {
                if (hit.collider.CompareTag("Player"))
                {
                    return true;
                }
            }
        }
        return false;
    }

    private Vector3 FindNearestCover()
    {
        Vector3 nearestCover = coverPoints[0].position;
        float closestDistance = Vector3.Distance(transform.position, nearestCover);

        foreach (Transform cover in coverPoints)
        {
            float distance = Vector3.Distance(transform.position, cover.position);
            if (distance < closestDistance)
            {
                nearestCover = cover.position;
                closestDistance = distance;
            }
        }
        return nearestCover;
    }

    private void MoveToCover(Vector3 coverPosition)
    {
        agent.SetDestination(coverPosition);
    }

    private void CheckStateTransitions()
    {
        if (currentState == AIState.Patrolling && distanceToPlayer < sightRange)
        {
            currentState = AIState.Chasing;
        }
        else if (currentState == AIState.Chasing && distanceToPlayer > chaseRange)
        {
            currentState = AIState.Patrolling;
        }

        else if (currentState == AIState.Chasing && distanceToPlayer < 10f )
        {
            currentState = AIState.Stalking;
        }
        
    }

    private void CheckIfSeen()
    {
        RaycastHit hit;

        Vector3 directionToAI = transform.position - playerCamera.position;
        if (Physics.Raycast(playerCamera.position, directionToAI, out hit))
        {
            if (hit.transform == transform)
            {
                currentState = AIState.Chasing;
                Debug.Log("Player looked at enemy, Chase mode activated");
            }
        }
    }

    private void ChaseState()
    {
       if (distanceToPlayer < chaseRange)
       {
            agent.SetDestination(target.position);
       }
        else
        {
            currentState = AIState.Stalking;
        } 
    }
}

Editor is loading...
Leave a Comment