using UnityEngine; public class VehicleTracker : MonoBehaviour { [SerializeField] private float _leadOffset = 5f; [SerializeField] private float _leadMultiplier = 0.1f; [SerializeField] private float _sideOffset = 0f; private bool _isOffTrack = false; private float _offTrackTimer = 0f; private float _trackerSpeed = 0f; private float _distanceTraveled = 0f; private float _speedLeadOffset = 50f; private float _speedLeadMultiplier = 0.2f; private float _offsetTimerRandom = 0f; private RaycastHit _surfaceHit; private Vector3 _deltaToWaypoint = Vector3.zero; private Vector3 _previousPos = Vector3.zero; private Vector3 _offsetToTarget = Vector3.zero; private RoutePoint _currentWaypoint = new RoutePoint(); private Transform _targetTracker = null; private VehicleController _linkedController = null; public Vector3 TargetPos => _targetTracker != null ? _targetTracker.position : Vector3.zero; private float VehicleSpeed => _linkedController != null ? _linkedController.LocalVelocity.z : 0f; public WaypointCircuit waypointsCircuit; private float _offsetSwitchTimer; private void Start() { _linkedController = GetComponent(); _targetTracker = new GameObject(name + " Tracker Target").transform; _targetTracker.SetParent(transform); _targetTracker.localPosition = Vector3.zero; _targetTracker.localRotation = Quaternion.identity; _distanceTraveled = 0f; _offsetTimerRandom = Random.Range(2.5f, 15f); _offsetSwitchTimer = _offsetTimerRandom; } private void Update() { if (_linkedController.Running && _linkedController.AIControlled) { _offsetSwitchTimer += Time.deltaTime; if (_offsetSwitchTimer >= _offsetTimerRandom) { _offsetSwitchTimer = 0; _sideOffset = 6f * Mathf.Sin(Time.time * Time.deltaTime * _offsetTimerRandom); } } if (_isOffTrack) { _offTrackTimer += Time.deltaTime; if (_offTrackTimer > 3f) { _isOffTrack = false; _offTrackTimer = 0f; ResetToTrack(); } } else { _offTrackTimer = 0f; } } private void FixedUpdate() { if (!_linkedController.Running) { _isOffTrack = false; return; } if (Physics.Raycast(transform.position - Vector3.down, -transform.up, out _surfaceHit, 10f)) { _isOffTrack = _surfaceHit.collider.CompareTag("Ground"); Debug.Log("_isOffTrack: " + _isOffTrack); } else { _isOffTrack = false; } UpdateWaypointTracking(); } private void UpdateWaypointTracking() { if (Time.deltaTime > 0f) _trackerSpeed = VehicleSpeed; _targetTracker.position = waypointsCircuit.GetRoutePoint(_distanceTraveled + _leadOffset + _leadMultiplier * _trackerSpeed).position + Vector3.right * _sideOffset; _targetTracker.rotation = Quaternion.LookRotation(waypointsCircuit.GetRoutePoint(_distanceTraveled + _speedLeadOffset + _speedLeadMultiplier * _trackerSpeed).direction); _currentWaypoint = waypointsCircuit.GetRoutePoint(_distanceTraveled); _deltaToWaypoint = _currentWaypoint.position - transform.position; if (Vector3.Dot(_deltaToWaypoint, _currentWaypoint.direction) < 0f) _distanceTraveled += _deltaToWaypoint.magnitude * 0.5f; _previousPos = transform.position; } private void ResetToTrack() { _linkedController.DisableVehicle(); transform.position = _targetTracker.position + new Vector3(0, 0.5f, 0); transform.rotation = _targetTracker.rotation; _linkedController.EnableVehicle(); } } //using UnityEngine; //public class VehicleTracker : MonoBehaviour //{ // [SerializeField] float _lookAheadForTargetOffset = 5f; // [SerializeField] float _lookAheadForTargetFactor = 0.1f; // [SerializeField] float _offset = 0f; // private bool _notOnTrack = false; // private float _respawnTimer = 0f; // private float _speed = 0f; // private float _progressDistance = 0f; // private float _lookAheadForSpeedOffset = 50f; // private float _lookAheadForSpeedFactor = 0.2f; // private float _randomTime = 0f; // private RaycastHit _hit; // private Vector3 _progressDelta = Vector3.zero; // private Vector3 _lastPosition = Vector3.zero; // private Vector3 _targetDelta = Vector3.zero; // private RoutePoint _progressPoint = new RoutePoint(); // private Transform _target = null; // private VehicleController _controller = null; // public Vector3 TargetPos => _target != null ? _target.position : Vector3.zero; // private float Speed => _controller != null ? _controller.CarVelocity.z : 0f; // public WaypointCircuit Waypoint; // float offsetTimer; // private void Start() // { // _controller = GetComponent(); // _target = new GameObject(name + " Waypoint Target").transform; // _target.SetParent(transform); // _target.localPosition = Vector3.zero; // _target.localRotation = Quaternion.identity; // _progressDistance = 0f; // _randomTime = Random.Range(2.5f, 15f); // offsetTimer = _randomTime; // } // private void Update() // { // if (_controller.CanRun && _controller.IsAI) // { // offsetTimer += Time.deltaTime; // if (offsetTimer >= _randomTime) // { // offsetTimer = 0; // _offset = 6f * Mathf.Sin(Time.time * Time.deltaTime * _randomTime); // } // } // if (_notOnTrack) // { // _respawnTimer += Time.deltaTime; // if (_respawnTimer > 1f) // { // //if (_controller.IsAI == false) // // GamePlayUI.Instance?.Respawning(_notOnTrack); // } // if (_respawnTimer > 3f) // { // _notOnTrack = false; // _respawnTimer = 0f; // RespawnOnRoad(); // } // } // else // { // _respawnTimer = 0f; // //if (_controller.IsAI == false) // // GamePlayUI.Instance?.Respawning(_notOnTrack); // } // // FollowRoute(); // Uncomment if you want to call it from Update // } // private void FixedUpdate() // { // if (_controller.CanRun == false) // { // _notOnTrack = false; // return; // } // if (Physics.Raycast(transform.position - Vector3.down, -transform.up, out _hit, 10f)) // { // _notOnTrack = _hit.collider.CompareTag("Ground"); // if (!_notOnTrack) // { // if (Physics.Raycast(transform.position + Vector3.forward, transform.forward, out _hit, 5f)) // _notOnTrack = _hit.collider.CompareTag("Wall"); // else // _notOnTrack = false; // } // } // else // { // _notOnTrack = false; // } // FollowRoute(); // } // private void FollowRoute() // { // if (Time.deltaTime > 0f) // _speed = Speed; // _target.position = Waypoint.GetRoutePoint(_progressDistance + _lookAheadForTargetOffset + _lookAheadForTargetFactor * _speed).position + Vector3.right * _offset; // _target.rotation = Quaternion.LookRotation(Waypoint.GetRoutePoint(_progressDistance + _lookAheadForSpeedOffset + _lookAheadForSpeedFactor * _speed).direction); // _progressPoint = Waypoint.GetRoutePoint(_progressDistance); // _progressDelta = _progressPoint.position - transform.position; // if (Vector3.Dot(_progressDelta, _progressPoint.direction) < 0f) // _progressDistance += _progressDelta.magnitude * 0.5f; // _lastPosition = transform.position; // } // private void RespawnOnRoad() // { // _controller.Sleep(); // transform.position = _target.position + new Vector3(0, 0.5f, 0); // transform.rotation = _target.rotation; // _controller.WakeUp(); // } //}