117 lines
3.7 KiB
C#
117 lines
3.7 KiB
C#
using UnityEngine;
|
|
|
|
namespace OmniVehicleAi
|
|
{
|
|
public class TurnRadiusAssistant : MonoBehaviour
|
|
{
|
|
[Header("References")]
|
|
public AIVehicleController aiVehicleController; // Reference to your AI vehicle controller
|
|
public bool overrideInput = false;
|
|
|
|
[Range(0, 1)]
|
|
public float accelerationInput = 0.1f;
|
|
|
|
private Transform VehicleTransform;
|
|
public float turnRadius;
|
|
|
|
// Number of frames to wait between position samples
|
|
public int framesBetweenSamples = 25; // You can set this in the Inspector
|
|
|
|
private int framesElapsed = 0;
|
|
private int step = 0;
|
|
|
|
// Positions
|
|
private Vector3 prevPrevPos;
|
|
private Vector3 prevPos;
|
|
private Vector3 currPos;
|
|
|
|
void Start()
|
|
{
|
|
VehicleTransform = aiVehicleController.vehicleTransform;
|
|
|
|
// Initialize positions
|
|
prevPrevPos = VehicleTransform.position;
|
|
|
|
// Initialize frame counter and step
|
|
framesElapsed = 0;
|
|
step = 0;
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
if (overrideInput) { aiVehicleController.OverrideInput(accelerationInput, 1, 0); }
|
|
}
|
|
|
|
void FixedUpdate()
|
|
{
|
|
framesElapsed++;
|
|
|
|
if (framesElapsed >= framesBetweenSamples)
|
|
{
|
|
framesElapsed = 0;
|
|
step++;
|
|
|
|
if (step == 1)
|
|
{
|
|
// First sample after starting or after calculation
|
|
prevPos = VehicleTransform.position;
|
|
}
|
|
else if (step == 2)
|
|
{
|
|
// Second sample
|
|
currPos = VehicleTransform.position;
|
|
|
|
// Calculate turn radius after collecting three positions
|
|
turnRadius = CalculateTurnRadius(prevPrevPos, prevPos, currPos);
|
|
|
|
// Optionally, display the turn radius
|
|
// Debug.Log("Turn Radius: " + turnRadius);
|
|
|
|
// In the same frame, reset prevPrevPos for the next calculation cycle
|
|
prevPrevPos = VehicleTransform.position;
|
|
|
|
// Reset step to begin the next cycle
|
|
step = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
float CalculateTurnRadius(Vector3 p1, Vector3 p2, Vector3 p3)
|
|
{
|
|
// Extract X and Z components (assuming movement on XZ-plane)
|
|
float x1 = p1.x;
|
|
float z1 = p1.z;
|
|
float x2 = p2.x;
|
|
float z2 = p2.z;
|
|
float x3 = p3.x;
|
|
float z3 = p3.z;
|
|
|
|
// Calculate the determinant (D)
|
|
float D = 2 * (x1 * (z2 - z3) + x2 * (z3 - z1) + x3 * (z1 - z2));
|
|
|
|
// Check for colinear points
|
|
if (Mathf.Abs(D) < 0.0001f)
|
|
{
|
|
// Points are nearly colinear; return infinity as radius
|
|
return Mathf.Infinity;
|
|
}
|
|
|
|
// Calculate the circle's center (Ux, Uz)
|
|
float x1SqPlusZ1Sq = x1 * x1 + z1 * z1;
|
|
float x2SqPlusZ2Sq = x2 * x2 + z2 * z2;
|
|
float x3SqPlusZ3Sq = x3 * x3 + z3 * z3;
|
|
|
|
float Ux = (x1SqPlusZ1Sq * (z2 - z3) + x2SqPlusZ2Sq * (z3 - z1) + x3SqPlusZ3Sq * (z1 - z2)) / D;
|
|
float Uz = (x1SqPlusZ1Sq * (x3 - x2) + x2SqPlusZ2Sq * (x1 - x3) + x3SqPlusZ3Sq * (x2 - x1)) / D;
|
|
|
|
// Calculate the radius
|
|
float dx = x1 - Ux;
|
|
float dz = z1 - Uz;
|
|
float radius = Mathf.Sqrt(dx * dx + dz * dz);
|
|
|
|
return radius;
|
|
}
|
|
|
|
}
|
|
}
|