/* * author: ryan lin * date: 30/7/2024 * description: vehicular ai behaviour */ using System.Collections; using UnityEngine; /// /// TODO /// public class AICar : MonoBehaviour { /// /// TODO /// [SerializeField] private Transform carPosition; /// /// TODO /// [SerializeField] private float stoppingDistance; /// /// TODO /// [SerializeField] private float slowingSpeed; /// /// TODO /// [SerializeField] private float slowingDistance; /// /// TODO /// [SerializeField] private float reverseDist; /// /// TODO /// private float _accelerationInput; /// /// TODO /// private float _angularDirection; /// /// TODO /// private CarController _car; /// /// TODO /// private string _currentState; /// /// TODO /// private Vector3 _dirToMove; /// /// TODO /// private float _distanceToTarget; /// /// TODO /// private Transform _driveTarget; /// /// TODO /// // FIXME: use an enum or something private string _nextState; /// /// TODO /// private float _turnInput; /// /// TODO /// private float _verticalDirection; /// /// TODO /// private void Awake() { var hasChild = false; var i = 0; while (!hasChild) { var test = gameObject.transform.GetChild(i).gameObject; if (test.name == "Target") { _driveTarget = test.transform; hasChild = true; } else { i++; } } _car = GetComponent(); _currentState = "Stopped"; _nextState = _currentState; ChangeState(); } /// /// TODO /// private void Update() { _currentState = _nextState; } /// /// TODO /// private void ChangeState() { StartCoroutine(_currentState); } /// /// TODO /// private void Steering() { _angularDirection = Vector3.SignedAngle(carPosition.transform.forward, (_driveTarget.position - carPosition.transform.position).normalized, Vector3.up); if (_angularDirection < 0) _turnInput = -1; else _turnInput = 1; } /// /// TODO /// private IEnumerator Stopped() { while (_currentState == "Stopped") { _distanceToTarget = Vector3.Distance(carPosition.position, _driveTarget.position); _car.braking = true; _accelerationInput = 0f; _turnInput = 0f; if (_distanceToTarget > stoppingDistance) _nextState = "Slowed"; yield return new WaitForSeconds(1); } ChangeState(); } /// /// TODO /// private IEnumerator Slowed() { _car.braking = false; while (_currentState == "Slowed") { _verticalDirection = Vector3.Dot(carPosition.transform.forward, (_driveTarget.position - carPosition.transform.position).normalized); _distanceToTarget = Vector3.Distance(carPosition.position, _driveTarget.position); if (_verticalDirection > 0) { if (carPosition.GetComponent().velocity.magnitude > slowingSpeed) _accelerationInput = -1; else _accelerationInput = 1; } else { if (_distanceToTarget < reverseDist) _accelerationInput = -1; else _accelerationInput = 1; } Steering(); SlowedCheck(); _car.SetInputs(_accelerationInput, _turnInput); yield return new WaitForEndOfFrame(); } ChangeState(); } /// /// TODO /// private IEnumerator Driving() { _car.braking = false; while (_currentState == "Driving") { _verticalDirection = Vector3.Dot(carPosition.transform.forward, (_driveTarget.position - carPosition.transform.position).normalized); _distanceToTarget = Vector3.Distance(carPosition.position, _driveTarget.position); _accelerationInput = 1; Steering(); if (_distanceToTarget < slowingDistance) _nextState = "Slowed"; _car.SetInputs(_accelerationInput, _turnInput); yield return new WaitForEndOfFrame(); } ChangeState(); } /// /// TODO /// private void SlowedCheck() { if (_distanceToTarget < stoppingDistance) _nextState = "Stopped"; if (_distanceToTarget > slowingDistance) _nextState = "Driving"; } }