Tweaked AI parameters Improved AI behaviour to avoid getting stuck near walls Changed boost conditions
120 lines
4.2 KiB
C#
120 lines
4.2 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
public class AIController : MonoBehaviour
|
|
{
|
|
public GameObject ball;
|
|
public Transform targetGoal;
|
|
public Vector3 inputVector;
|
|
public float turnRadius = 1;
|
|
public float destinationOffset;
|
|
public float maxBoostDist = 3;
|
|
|
|
public float distanceToTarget; //Distance to the point, placed behind the ball
|
|
public float angleToDestination;
|
|
public float angleToBall;
|
|
public float distanceToBall;
|
|
|
|
private Vector3 destination;
|
|
private Vector3 directionVector;
|
|
private float rotationTimeout = 0;
|
|
// Start is called before the first frame update
|
|
void Start()
|
|
{
|
|
|
|
}
|
|
|
|
// Update is called once per frame
|
|
void Update()
|
|
{
|
|
Vector3 ballPosition = this.ball.transform.position;
|
|
Vector3 goalDirection = ballPosition - this.targetGoal.position;
|
|
this.destination = ballPosition + goalDirection.normalized * this.destinationOffset;
|
|
this.directionVector = this.destination - this.transform.position;
|
|
|
|
//Use "right" to offset the angle by 90 deg. This gives us a positive/negative value
|
|
// depending on the direction we have to rotate
|
|
this.angleToDestination = Vector3.Dot(this.transform.right, this.directionVector.normalized);
|
|
|
|
this.angleToBall = Mathf.Acos(Vector3.Dot((ballPosition - this.transform.position).normalized, this.transform.forward)) * Mathf.Rad2Deg;
|
|
this.angleToBall = this.Angle360(transform.position, ballPosition, Vector3.right);
|
|
this.distanceToTarget = Vector3.Distance(this.transform.position, this.destination);
|
|
this.distanceToBall = Vector3.Distance(this.transform.position, ballPosition);
|
|
|
|
}
|
|
|
|
float Angle360(Vector3 from, Vector3 to, Vector3 right)
|
|
{
|
|
float angle = Vector3.Angle(from, to);
|
|
return (Vector3.Angle(right, to) > 90f) ? 360f - angle : angle;
|
|
}
|
|
|
|
private void OnDrawGizmos()
|
|
{
|
|
Debug.DrawLine(this.transform.position, this.destination, Color.yellow, 0f, false);
|
|
Debug.DrawLine(this.targetGoal.position, this.destination, Color.yellow, 0f, false);
|
|
Gizmos.DrawSphere(this.destination, 1);
|
|
Debug.DrawRay(transform.position, this.transform.forward * 3.8f, Color.white, .5f);
|
|
Debug.DrawRay(transform.position, this.transform.forward * 10, Color.green);
|
|
|
|
|
|
}
|
|
|
|
|
|
public float[] GetInputs()
|
|
{
|
|
float[] inputs = new float[3];
|
|
|
|
inputs[AiInputs.VERTICAL] = 0;
|
|
inputs[AiInputs.BOOST] = 0;
|
|
|
|
//Move forward if we are too far away
|
|
if (this.distanceToTarget > 4)
|
|
{
|
|
inputs[AiInputs.VERTICAL] = 1;
|
|
}
|
|
|
|
RaycastHit hit;
|
|
//If we hit something head on, stop, drop and rotate (emergency rotate)
|
|
if (Physics.Raycast(transform.position, this.transform.forward, out hit, 3.8f))
|
|
{
|
|
this.rotationTimeout = .2f;
|
|
}
|
|
|
|
//Rotate if we are close enough to the target (behind the ball) but not if emergency rotation is active
|
|
inputs[AiInputs.HORIZONTAL] = Mathf.Floor(this.angleToDestination * 10) / 10;
|
|
if (this.distanceToTarget < this.turnRadius && this.rotationTimeout < 0)
|
|
{
|
|
inputs[AiInputs.HORIZONTAL] = Mathf.Floor(-this.angleToBall * 10) / 10;
|
|
}
|
|
|
|
this.rotationTimeout -= Time.deltaTime;
|
|
if(rotationTimeout > 0)
|
|
{
|
|
inputs[AiInputs.HORIZONTAL] = .5f;
|
|
}
|
|
|
|
|
|
|
|
//Shoot a ray backwards and boost if we are close enough to the target (behind the ball) to avoid shooting towards our own goal
|
|
if (Physics.Raycast(transform.position, -this.transform.forward, out hit, 15))
|
|
{
|
|
if (hit.transform.tag == "Ball" && this.distanceToTarget < this.maxBoostDist)
|
|
{
|
|
inputs[AiInputs.BOOST] = 1;
|
|
}
|
|
}
|
|
|
|
this.inputVector = new Vector3(inputs[AiInputs.HORIZONTAL], inputs[AiInputs.VERTICAL], inputs[AiInputs.BOOST]);
|
|
//Left/Right, Fwd/Bkwd, Boost
|
|
return inputs;
|
|
}
|
|
}
|
|
|
|
public static class AiInputs
|
|
{
|
|
public const int HORIZONTAL = 0;
|
|
public const int VERTICAL = 1;
|
|
public const int BOOST = 2;
|
|
} |