/* * author: ryan lin * date: 30/7/2024 * description: 'standard' npc ai behaviour */ using System.Collections; using UnityEngine; using UnityEngine.AI; using Random = System.Random; /// /// TODO /// public class AI : MonoBehaviour { /// /// to save resources when referring to the speed of this AI if its human /// private static readonly int AnimatorSpeed = Animator.StringToHash("Speed"); /// /// 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() { _animator = GetComponent(); _currentState = "Strolling"; _agent = GetComponent(); _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() { _animator.SetFloat(AnimatorSpeed, _agent.velocity.magnitude); _currentState = _nextState; } /// /// to change the scene when needed /// private 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") { if (!_destinationPointSet) SearchWalkPoint(); else _agent.SetDestination(destinationCoord); if ((transform.position - destinationCoord).magnitude < 1f) _destinationPointSet = false; yield return new WaitForSeconds(1f); } ChangeState(); } }