/*
* author: lin hengrui ryan
* date: 30/7/2024
* description: ai code for the different ai in the game
*/
using System.Collections;
using UnityEngine;
using UnityEngine.AI;
using Random = System.Random;
public class AI : MonoBehaviour
{
///
/// the types of ai that this game object can be
///
public enum EntityType
{
Human,
Car
}
///
/// to save resources when referring to the speed of this ai if its a human
///
private static readonly int AnimatorSpeed = Animator.StringToHash("Speed");
///
/// to show the entity types in the inspector as a dropdown
///
public EntityType entityType;
///
/// set the layers the AI can be on
///
public LayerMask walkableLayers;
///
/// the destination coordinate of the AI
///
public Vector3 destinationCoord;
///
/// the range that the AI can set as their destination
///
public int movingRange;
///
/// the nav mash agent that is on this AI
///
private NavMeshAgent _agent;
///
/// the animator that is attached to this AI if applicable
///
private Animator _animator;
///
/// the current state that the AI is at this point in time
///
private string _currentState;
///
/// a bool to check if the destination point is set
///
private bool _destinationPointSet;
///
/// the state that the AI will be on the next update
///
private string _nextState;
///
/// to set initial values
///
public void Awake()
{
_agent = GetComponent();
if (entityType == EntityType.Human)
{
_animator = GetComponent();
_currentState = "Strolling";
}
_nextState = _currentState;
ChangeState();
}
///
/// to update the speed of the AI to the animator each frame and to update any state changes to the ai
///
public void Update()
{
if (entityType == EntityType.Human) _animator.SetFloat(AnimatorSpeed, _agent.velocity.magnitude);
_currentState = _nextState;
}
///
/// to change the scene when needed
///
public void ChangeState()
{
StartCoroutine(_currentState);
}
///
/// to set a random x and y coordinate for the AI to go to
///
private void SearchWalkPoint()
{
var rand = new Random();
float randomX = rand.Next(-movingRange * 100, movingRange * 100);
float randomZ = rand.Next(-movingRange * 100, movingRange * 100);
destinationCoord = new Vector3(
transform.position.x + randomX / 100,
transform.position.y,
transform.position.z + randomZ / 100
);
if (Physics.Raycast(destinationCoord, -transform.up, 2f, walkableLayers)) _destinationPointSet = true;
}
///
/// a state that the AI wonders around using the SearchWalkPoint function to find a location for the AI to go to
///
private IEnumerator Strolling()
{
SearchWalkPoint();
while (_currentState == "Strolling")
{
Debug.Log("strolling");
if (!_destinationPointSet)
SearchWalkPoint();
else
_agent.SetDestination(destinationCoord);
if ((transform.position - destinationCoord).magnitude < 1f) _destinationPointSet = false;
yield return new WaitForSeconds(1f);
}
ChangeState();
}
}