This repository has been archived on 2024-08-16. You can view files and clone it, but cannot push or open issues or pull requests.
sota/RunningLateGame/Assets/Scripts/AiCar.cs

238 lines
6.5 KiB
C#
Raw Normal View History

/*
* author: ryan lin
* date: 30/7/2024
2024-08-10 21:40:22 +00:00
* description: making the car go to a game object's position
*/
using System.Collections;
2024-08-07 06:55:21 +00:00
using UnityEngine;
/// <summary>
2024-08-10 21:40:22 +00:00
/// making the car go to a game object's position
/// </summary>
2024-08-07 06:55:21 +00:00
public class AICar : MonoBehaviour
{
/// <summary>
2024-08-10 21:40:22 +00:00
/// reference to the car model
/// </summary>
2024-08-07 06:55:21 +00:00
[SerializeField] private Transform carPosition;
/// <summary>
2024-08-10 21:40:22 +00:00
/// the radius of which the car can stop in
/// </summary>
2024-08-07 06:55:21 +00:00
[SerializeField] private float stoppingDistance;
/// <summary>
2024-08-10 21:40:22 +00:00
/// the speed of which the car needs to be at/under to when it is in the slowed state
/// </summary>
2024-08-07 06:55:21 +00:00
[SerializeField] private float slowingSpeed;
/// <summary>
2024-08-10 21:40:22 +00:00
/// the radius that the car switches to the slowed state
/// </summary>
2024-08-07 06:55:21 +00:00
[SerializeField] private float slowingDistance;
/// <summary>
2024-08-10 21:40:22 +00:00
/// the distance that the car is allowed to reverse
/// </summary>
2024-08-07 06:55:21 +00:00
[SerializeField] private float reverseDist;
/// <summary>
2024-08-10 21:40:22 +00:00
/// the acceleration input for the car script
/// </summary>
2024-08-07 06:55:21 +00:00
private float _accelerationInput;
/// <summary>
2024-08-10 21:40:22 +00:00
/// the angular input for the car script
/// </summary>
2024-08-07 06:55:21 +00:00
private float _angularDirection;
/// <summary>
2024-08-10 21:40:22 +00:00
/// reference to the car script
/// </summary>
private CarController _car;
/// <summary>
2024-08-10 21:40:22 +00:00
/// the current state the car is in for fsm
/// </summary>
private string _currentState;
/// <summary>
2024-08-10 21:40:22 +00:00
/// the distance that the car is from the target
/// </summary>
2024-08-07 06:55:21 +00:00
private float _distanceToTarget;
/// <summary>
2024-08-10 21:40:22 +00:00
/// the transform of the target
/// </summary>
2024-08-07 06:55:21 +00:00
private Transform _driveTarget;
2024-08-10 21:40:22 +00:00
private NextState _nextState;
/// <summary>
2024-08-10 21:40:22 +00:00
/// the turn input for the car script
/// </summary>
2024-08-07 06:55:21 +00:00
private float _turnInput;
/// <summary>
2024-08-10 21:40:22 +00:00
/// the car is in front or behind the target, a positive will be returned if the car is in front
/// </summary>
2024-08-07 06:55:21 +00:00
private float _verticalDirection;
/// <summary>
2024-08-10 21:40:22 +00:00
/// initialise values
/// </summary>
2024-08-07 06:55:21 +00:00
private void Awake()
{
var hasChild = false;
var i = 0;
while (!hasChild)
{
2024-08-09 18:27:32 +00:00
var test = gameObject.transform.GetChild(i).gameObject;
2024-08-07 06:55:21 +00:00
if (test.name == "Target")
{
_driveTarget = test.transform;
hasChild = true;
}
else
{
i++;
}
}
_car = GetComponent<CarController>();
2024-08-10 21:40:22 +00:00
_nextState = NextState.Stopped;
2024-08-11 05:51:29 +00:00
_currentState = "Stopped";
StartCoroutine(_currentState);
2024-08-07 06:55:21 +00:00
}
/// <summary>
2024-08-10 21:40:22 +00:00
/// to update the next state value when it changes
/// </summary>
2024-08-07 06:55:21 +00:00
private void Update()
{
2024-08-10 21:40:22 +00:00
if (_nextState == NextState.Stopped)
_currentState = "Stopped";
else if (_nextState == NextState.Slowed)
_currentState = "Slowed";
else
_currentState = "Driving";
2024-08-07 06:55:21 +00:00
}
/// <summary>
2024-08-10 21:40:22 +00:00
/// is called at the end of states to call the next state
/// </summary>
2024-08-07 06:55:21 +00:00
private void ChangeState()
{
StartCoroutine(_currentState);
}
/// <summary>
2024-08-10 21:40:22 +00:00
/// a function that allows the car to steer
/// </summary>
2024-08-07 06:55:21 +00:00
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;
}
/// <summary>
2024-08-10 21:40:22 +00:00
/// to put the car in a stopped state
/// </summary>
2024-08-07 06:55:21 +00:00
private IEnumerator Stopped()
{
2024-08-10 21:40:22 +00:00
while (_nextState != NextState.Stopped)
2024-08-07 06:55:21 +00:00
{
_distanceToTarget = Vector3.Distance(carPosition.position, _driveTarget.position);
2024-08-07 06:55:21 +00:00
_car.braking = true;
_accelerationInput = 0f;
_turnInput = 0f;
2024-08-10 21:40:22 +00:00
if (_distanceToTarget > stoppingDistance) _nextState = NextState.Slowed;
2024-08-07 06:55:21 +00:00
yield return new WaitForSeconds(1);
}
2024-08-07 06:55:21 +00:00
ChangeState();
}
/// <summary>
2024-08-10 21:40:22 +00:00
/// to put the car in a slowed state
/// </summary>
2024-08-07 06:55:21 +00:00
private IEnumerator Slowed()
{
_car.braking = false;
2024-08-10 21:40:22 +00:00
while (_nextState != NextState.Slowed)
2024-08-07 06:55:21 +00:00
{
_verticalDirection = Vector3.Dot(carPosition.transform.forward,
(_driveTarget.position - carPosition.transform.position).normalized);
_distanceToTarget = Vector3.Distance(carPosition.position, _driveTarget.position);
if (_verticalDirection > 0)
2024-08-07 06:55:21 +00:00
{
if (carPosition.GetComponent<Rigidbody>().velocity.magnitude > slowingSpeed)
_accelerationInput = -1;
else
_accelerationInput = 1;
}
else
{
if (_distanceToTarget < reverseDist)
_accelerationInput = -1;
else
_accelerationInput = 1;
}
2024-08-07 06:55:21 +00:00
Steering();
SlowedCheck();
_car.SetInputs(_accelerationInput, _turnInput);
yield return new WaitForEndOfFrame();
}
2024-08-07 06:55:21 +00:00
ChangeState();
}
/// <summary>
2024-08-10 21:40:22 +00:00
/// to put the car in a driving state
/// </summary>
2024-08-07 06:55:21 +00:00
private IEnumerator Driving()
{
_car.braking = false;
2024-08-10 21:40:22 +00:00
while (_nextState != NextState.Driving)
2024-08-07 06:55:21 +00:00
{
_verticalDirection = Vector3.Dot(carPosition.transform.forward,
(_driveTarget.position - carPosition.transform.position).normalized);
_distanceToTarget = Vector3.Distance(carPosition.position, _driveTarget.position);
_accelerationInput = 1;
2024-08-07 06:55:21 +00:00
Steering();
2024-08-10 21:40:22 +00:00
if (_distanceToTarget < slowingDistance) _nextState = NextState.Slowed;
2024-08-07 06:55:21 +00:00
_car.SetInputs(_accelerationInput, _turnInput);
yield return new WaitForEndOfFrame();
}
2024-08-07 06:55:21 +00:00
ChangeState();
}
/// <summary>
2024-08-10 21:40:22 +00:00
/// a function to check if the car should be a slowed state
/// </summary>
2024-08-07 06:55:21 +00:00
private void SlowedCheck()
{
2024-08-10 21:40:22 +00:00
if (_distanceToTarget < stoppingDistance) _nextState = NextState.Stopped;
2024-08-11 05:51:29 +00:00
if (_distanceToTarget > slowingDistance) _nextState = NextState.Driving;
2024-08-10 21:40:22 +00:00
}
2024-08-07 06:55:21 +00:00
2024-08-10 21:40:22 +00:00
/// <summary>
/// enum of states that the car can be in
/// </summary>
private enum NextState
{
Slowed,
Stopped,
Driving
2024-08-07 06:55:21 +00:00
}
}