using System.Collections.Generic; using UnityEngine; using UnityEngine.AI; public class PointsManager : MonoBehaviour { [Header("Точки для разных задач")] public Transform[] dancePoints; public Transform[] shootPoints; // Словарь: имя группы занятые точки private readonly Dictionary> occupied = new(); private void Awake() { // Инициализация групп occupied["dance"] = new HashSet(); occupied["shoot"] = new HashSet(); ValidateOnNavMesh(dancePoints); ValidateOnNavMesh(shootPoints); } private void ValidateOnNavMesh(Transform[] points) { foreach (var p in points) { if (p == null) continue; if (NavMesh.SamplePosition(p.position, out NavMeshHit hit, 2f, NavMesh.AllAreas)) { p.position = hit.position; } else { Debug.LogWarning($"{p.name} не попал на NavMesh!"); } } } public Transform GetRandomFreePoint(string group, Transform[] points) { if (points == null || points.Length == 0) return null; var freePoints = new List(); foreach (var p in points) { if (!occupied[group].Contains(p)) freePoints.Add(p); } if (freePoints.Count == 0) return null; Transform chosen = freePoints[Random.Range(0, freePoints.Count)]; occupied[group].Add(chosen); return chosen; } public Transform GetNearestFreePoint(string group, Transform[] points, Vector3 fromPosition) { Transform nearest = null; float minDist = float.MaxValue; foreach (var p in points) { if (occupied[group].Contains(p)) continue; float dist = Vector3.Distance(fromPosition, p.position); if (dist < minDist) { minDist = dist; nearest = p; } } if (nearest != null) occupied[group].Add(nearest); return nearest; } public void FreePoint(string group, Transform point) { occupied[group].Remove(point); } public bool HasLineOfSight(Transform from, Transform to) { if (from == null || to == null) return false; Vector3 origin = from.position + Vector3.up * 1.5f; Vector3 target = to.position + Vector3.up * 1.0f; Vector3 direction = (target - origin).normalized; float distance = Vector3.Distance(origin, target); RaycastHit[] hits = Physics.RaycastAll(origin, direction, distance); foreach (var hit in hits) { // игнорируем самого врага if (hit.transform == to || hit.transform.IsChildOf(to)) continue; // если что-то попалось раньше врага — LOS закрыт #if UNITY_EDITOR Debug.DrawLine(origin, hit.point, Color.red, 1f); #endif return false; } #if UNITY_EDITOR Debug.DrawLine(origin, target, Color.green, 1f); #endif return true; } }