game: add car navigation to a target position

This commit is contained in:
Mark Joshwel 2024-08-05 17:56:43 +08:00
parent 429b96f0e1
commit 16d5b3faad
3 changed files with 123 additions and 37 deletions

View file

@ -1,7 +1,7 @@
/*
* author: lin hengrui ryan
* date: 30/7/2024
* description: ai code for the different ai in the game
* description: AI code for the different AI in the game
*/
using System.Collections;
@ -12,23 +12,10 @@
public class AI : MonoBehaviour
{
/// <summary>
/// the types of ai that this game object can be
/// </summary>
public enum EntityType
{
Human,
Car
}
/// <summary>
/// to save resources when referring to the speed of this ai if its a human
/// to save resources when referring to the speed of this AI if its human
/// </summary>
private static readonly int AnimatorSpeed = Animator.StringToHash("Speed");
/// <summary>
/// to show the entity types in the inspector as a dropdown
/// </summary>
public EntityType entityType;
/// <summary>
/// set the layers the AI can be on
@ -70,35 +57,38 @@ public enum EntityType
/// </summary>
private string _nextState;
/// <summary>
/// to set initial values
/// </summary>
public void Awake()
{
_animator = GetComponent<Animator>();
_currentState = "Strolling";
_agent = GetComponent<NavMeshAgent>();
if (entityType == EntityType.Human)
{
_animator = GetComponent<Animator>();
_currentState = "Strolling";
}
_animator = GetComponent<Animator>();
_currentState = "Strolling";
_nextState = _currentState;
ChangeState();
}
/// <summary>
/// to update the speed of the AI to the animator each frame and to update any state changes to the ai
/// to update the speed of the AI to the animator each frame and to update any state changes to the AI
/// </summary>
public void Update()
{
if (entityType == EntityType.Human) _animator.SetFloat(AnimatorSpeed, _agent.velocity.magnitude);
_animator.SetFloat(AnimatorSpeed, _agent.velocity.magnitude);
_currentState = _nextState;
}
/// <summary>
/// to change the scene when needed
/// </summary>
public void ChangeState()
private void ChangeState()
{
StartCoroutine(_currentState);
}
@ -128,7 +118,6 @@ private IEnumerator Strolling()
while (_currentState == "Strolling")
{
Debug.Log("strolling");
if (!_destinationPointSet)
SearchWalkPoint();
else
@ -141,4 +130,4 @@ private IEnumerator Strolling()
ChangeState();
}
}
}

View file

@ -13,11 +13,11 @@ public enum Axel
public float acceleration;
public float turnAngle;
public List<Wheel> wheels;
public float brakeForce = 50.0f;
public float brakeForce;
public bool braking;
private float _currentAcceleration;
private float _currentTurn;
public bool braking;
private void FixedUpdate()
@ -27,11 +27,13 @@ private void FixedUpdate()
Brake();
}
public void SetInputs(float forwardAmount,float turnAmount)
public void SetInputs(float forwardAmount, float turnAmount)
{
_currentAcceleration = forwardAmount*acceleration;
_currentTurn = turnAmount*turnAngle;
_currentAcceleration = forwardAmount * acceleration;
_currentTurn = turnAmount * turnAngle;
}
public void Move()
{
foreach (var wheel in wheels) wheel.wheelCollider.motorTorque = _currentAcceleration;

View file

@ -1,19 +1,114 @@
using System;
using System.Collections;
using UnityEngine;
public class AICar : MonoBehaviour
{
private CarController _carController;
[SerializeField] private Transform carPosition;
[SerializeField] private float stoppingDistance;
[SerializeField] private float slowingSpeed;
[SerializeField] private float slowingDistance;
[SerializeField] private float reverseDist;
private CarController _car;
private string _currentState;
private Transform _driveTarget;
private string _nextState;
private void Awake()
{
_carController = GetComponent<CarController>();
var hasChild = false;
var i = 0;
GameObject test;
while (!hasChild)
{
test = gameObject.transform.GetChild(i).gameObject;
if (test.name == "Target")
{
_driveTarget = test.transform;
hasChild = true;
}
else
{
i++;
}
}
_car = GetComponent<CarController>();
_currentState = "Driving";
_nextState = _currentState;
ChangeState();
}
private void Update()
{
float forwardAmount = 1f;
float turnAmount = 1f;
_carController.SetInputs(forwardAmount,turnAmount);
_currentState = _nextState;
}
private void ChangeState()
{
StartCoroutine(_currentState);
}
private IEnumerator Driving()
{
_car = GetComponent<CarController>();
while (_currentState == "Driving")
{
var accelerationAmount = 0f;
var turnAmount = 0f;
var targetPosition = _driveTarget.position;
var dirToMove = (targetPosition - carPosition.transform.position).normalized;
var forwardsAmount = Vector3.Dot(carPosition.transform.forward, dirToMove);
var directionToDrive = Vector3.SignedAngle(carPosition.transform.forward, dirToMove, Vector3.up);
var distanceToTarget = Vector3.Distance(carPosition.position, targetPosition);
if (distanceToTarget >= stoppingDistance)
{
_car.braking = false;
//in front of target position
if (forwardsAmount > 0)
{
//closer than the slowing distance
if (distanceToTarget <= slowingDistance)
{
//the car is very fast
if (carPosition.GetComponent<Rigidbody>().velocity.magnitude > slowingSpeed)
accelerationAmount = -2;
else
accelerationAmount = 1;
}
else
{
accelerationAmount = 1;
}
}
else
{
if (distanceToTarget < reverseDist)
accelerationAmount = -1;
else
accelerationAmount = 1;
}
if (directionToDrive < 0)
turnAmount = 1;
else if (directionToDrive > 0)
turnAmount = -1;
else
turnAmount = 0;
}
else
{
_car.braking = true;
accelerationAmount = 0f;
turnAmount = 0f;
}
Debug.Log(carPosition.GetComponent<Rigidbody>().velocity.magnitude);
_car.SetInputs(accelerationAmount, turnAmount);
yield return new WaitForEndOfFrame();
}
}
}