155 lines
4.4 KiB
C#
155 lines
4.4 KiB
C#
using System.Collections;
|
|
using UnityEngine;
|
|
using Boxes;
|
|
|
|
public class VanController : MonoBehaviour
|
|
{
|
|
[Header("Движение")]
|
|
public float forwardSpeed = 5.0f;
|
|
public float moveSpeed = 10.0f;
|
|
|
|
[Header("Спавн коробок")]
|
|
public BoxData[] availableBoxes;
|
|
public float spawnInterval = 0.5f;
|
|
public float boxEjectionForce = 2f;
|
|
public float boxTorqueForce = 5f;
|
|
|
|
[Header("AI Уклонения")]
|
|
public float detectionDistance = 40f;
|
|
public LayerMask trafficLayer;
|
|
|
|
private int _currentLaneIndex = 3;
|
|
private float _targetX;
|
|
private bool _isChangingLane;
|
|
private float _totalSpawnWeight;
|
|
private bool _isAlive = true;
|
|
|
|
private int[] _safeLanesBuffer;
|
|
|
|
private void OnEnable()
|
|
{
|
|
GameEvents.OnPlayerDied += StopActivities;
|
|
}
|
|
|
|
private void OnDisable()
|
|
{
|
|
GameEvents.OnPlayerDied -= StopActivities;
|
|
}
|
|
|
|
void Start()
|
|
{
|
|
_targetX = transform.position.x;
|
|
|
|
_totalSpawnWeight = 0;
|
|
foreach (var box in availableBoxes)
|
|
{
|
|
_totalSpawnWeight += box.spawnWeight;
|
|
}
|
|
|
|
_safeLanesBuffer = new int[RoadManager.Instance.GetLanesCount()];
|
|
|
|
StartCoroutine(SpawnBoxesInfinitely());
|
|
StartCoroutine(AvoidanceRoutine());
|
|
}
|
|
|
|
void Update()
|
|
{
|
|
if (!_isAlive) return;
|
|
|
|
transform.Translate(Vector3.forward * forwardSpeed * Time.deltaTime);
|
|
Vector3 newPos = transform.position;
|
|
newPos.x = Mathf.Lerp(newPos.x, _targetX, Time.deltaTime * moveSpeed);
|
|
transform.position = newPos;
|
|
}
|
|
|
|
private void StopActivities() => _isAlive = false;
|
|
|
|
IEnumerator SpawnBoxesInfinitely()
|
|
{
|
|
while (_isAlive)
|
|
{
|
|
yield return new WaitForSeconds(spawnInterval);
|
|
SpawnPhysicalBox();
|
|
}
|
|
}
|
|
|
|
void SpawnPhysicalBox()
|
|
{
|
|
BoxData boxToSpawn = GetRandomBoxType();
|
|
if (boxToSpawn == null || boxToSpawn.boxPrefab == null) return;
|
|
|
|
GameObject box = SimpleObjectPool.Instance.Get(boxToSpawn.boxPrefab, transform.position, Random.rotation);
|
|
|
|
Box boxComponent = box.GetComponent<Box>();
|
|
if (boxComponent != null) boxComponent.Init(boxToSpawn);
|
|
|
|
Rigidbody rb = box.GetComponent<Rigidbody>();
|
|
if (rb != null)
|
|
{
|
|
rb.linearVelocity = Vector3.zero;
|
|
rb.angularVelocity = Vector3.zero;
|
|
rb.AddForce(Vector3.back * boxEjectionForce, ForceMode.Impulse);
|
|
rb.AddTorque(Random.insideUnitSphere * boxTorqueForce, ForceMode.Impulse);
|
|
}
|
|
}
|
|
|
|
BoxData GetRandomBoxType()
|
|
{
|
|
if (availableBoxes.Length == 0) return null;
|
|
float randomValue = Random.Range(0, _totalSpawnWeight);
|
|
float currentWeight = 0;
|
|
foreach (var boxData in availableBoxes)
|
|
{
|
|
currentWeight += boxData.spawnWeight;
|
|
if (randomValue <= currentWeight) return boxData;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
IEnumerator AvoidanceRoutine()
|
|
{
|
|
while (_isAlive)
|
|
{
|
|
yield return new WaitForSeconds(0.2f);
|
|
if (_isChangingLane) continue;
|
|
if (IsObstacleAhead()) TryToEvade();
|
|
}
|
|
}
|
|
|
|
bool IsObstacleAhead() => Physics.Raycast(transform.position, Vector3.forward, detectionDistance, trafficLayer);
|
|
|
|
void TryToEvade()
|
|
{
|
|
int safeLanesCount = 0;
|
|
int totalLanes = RoadManager.Instance.GetLanesCount();
|
|
|
|
for (int i = 0; i < totalLanes; i++)
|
|
{
|
|
if (i == _currentLaneIndex) continue;
|
|
|
|
float laneX = RoadManager.Instance.GetLaneX(i);
|
|
Vector3 checkPosition = new Vector3(laneX, transform.position.y, transform.position.z);
|
|
|
|
if (!Physics.Raycast(checkPosition, Vector3.forward, detectionDistance, trafficLayer))
|
|
{
|
|
_safeLanesBuffer[safeLanesCount] = i;
|
|
safeLanesCount++;
|
|
}
|
|
}
|
|
|
|
if (safeLanesCount > 0)
|
|
{
|
|
int chosenLane = _safeLanesBuffer[Random.Range(0, safeLanesCount)];
|
|
StartCoroutine(ChangeLane(chosenLane));
|
|
}
|
|
}
|
|
|
|
IEnumerator ChangeLane(int newLaneIndex)
|
|
{
|
|
_isChangingLane = true;
|
|
_currentLaneIndex = newLaneIndex;
|
|
_targetX = RoadManager.Instance.GetLaneX(newLaneIndex);
|
|
yield return new WaitForSeconds(0.6f);
|
|
_isChangingLane = false;
|
|
}
|
|
} |