Загрузка данных


using UnityEngine;
using UnityEngine.UI;

public class GunSightUI : MonoBehaviour
{
    [Header("Ссылки")]
    [SerializeField] private Camera worldSpaceCamera;
    [SerializeField] private Transform gunMuzzle; // Точка стрельбы (дуло орудия)
    [SerializeField] private RectTransform sightUI; // UI элемент прицела (крестик)
    [SerializeField] private Canvas parentCanvas; // Canvas, на котором находится прицел
    
    [Header("Настройки")]
    [SerializeField] private float maxRaycastDistance = 2000f; // Максимальная дистанция (2 км)
    [SerializeField] private LayerMask raycastLayerMask = ~0; // Слои для райкаста
    [SerializeField] private float projectileSpeed = 1000f; // Скорость снаряда м/с
    
    [Header("Настройки отображения")]
    [SerializeField] private float sightScale = 1.0f;
    
    // Компоненты
    private RectTransform rectTransform;
    private Image sightImage;
    
    // Данные о текущей точке прицеливания
    private Vector3 currentAimPointWorld = Vector3.zero;
    private float currentAimDistance = 0f;
    
    void Start()
    {
        // Получаем компоненты
        if (sightUI != null)
            rectTransform = sightUI;
        else
            rectTransform = GetComponent<RectTransform>();
            
        sightImage = GetComponent<Image>();
        
        if (worldSpaceCamera == null)
            worldSpaceCamera = Camera.main;
            
        if (parentCanvas == null)
            parentCanvas = GetComponentInParent<Canvas>();
            
        if (gunMuzzle == null)
        {
            // Пытаемся найти точку стрельбы автоматически
            PantsirRadarSystem radarSystem = FindObjectOfType<PantsirRadarSystem>();
            if (radarSystem != null && radarSystem.gun != null)
            {
                gunMuzzle = radarSystem.gun;
            }
        }
    }
    
    void Update()
    {
        UpdateSightPosition();
    }
    
    void UpdateSightPosition()
    {
        if (worldSpaceCamera == null || rectTransform == null || gunMuzzle == null)
            return;
            
        // Получаем расстояние до точки прицеливания
        float aimDistance = CalculateAimDistance();
        
        // Направление от точки выстрела через центр экрана
        Vector3 rayDirection = worldSpaceCamera.transform.forward;
        Vector3 rayOrigin = gunMuzzle.position;
        
        // Точка прицеливания на рассчитанной дистанции
        Vector3 aimPoint = rayOrigin + rayDirection * aimDistance;
        
        // Преобразуем мировую точку в экранные координаты
        Vector3 screenPoint = worldSpaceCamera.WorldToScreenPoint(aimPoint);
        
        // Проверяем, находится ли точка перед камерой
        if (screenPoint.z > 0)
        {
            // Преобразуем экранные координаты в координаты канваса
            Vector2 canvasPosition;
            RectTransformUtility.ScreenPointToLocalPointInRectangle(
                parentCanvas.transform as RectTransform,
                screenPoint,
                parentCanvas.renderMode == RenderMode.ScreenSpaceOverlay ? null : worldSpaceCamera,
                out canvasPosition
            );
            
            // Устанавливаем позицию прицела
            rectTransform.localPosition = canvasPosition;
            
            // Показываем прицел
            if (sightImage != null)
                sightImage.enabled = true;
                
            currentAimPointWorld = aimPoint;
            currentAimDistance = aimDistance;
        }
        else
        {
            // Скрываем прицел, если точка позади камеры
            if (sightImage != null)
                sightImage.enabled = false;
        }
    }
    
    float CalculateAimDistance()
    {
        Vector3 rayOrigin = gunMuzzle.position;
        Vector3 rayDirection = worldSpaceCamera.transform.forward;
        
        // Проверяем, есть ли захваченная цель
        if (PantsirRadarSystem.IsAnyTargetLocked && PantsirRadarSystem.LockedTargetPosition.HasValue)
        {
            Vector3 lockedTargetPos = PantsirRadarSystem.LockedTargetPosition.Value;
            
            // Рассчитываем точку упреждения
            Vector3 leadPoint = CalculateLeadPoint(lockedTargetPos);
            
            // Возвращаем расстояние до точки упреждения
            float distanceToLeadPoint = Vector3.Distance(rayOrigin, leadPoint);
            
            // Ограничиваем максимальной дистанцией
            return Mathf.Min(distanceToLeadPoint, maxRaycastDistance);
        }
        
        // Если нет захваченной цели - делаем райкаст
        RaycastHit hit;
        if (Physics.Raycast(rayOrigin, rayDirection, out hit, maxRaycastDistance, raycastLayerMask))
        {
            // Если луч уперся - возвращаем расстояние до точки попадания
            return hit.distance;
        }
        else
        {
            // Если луч не уперся - возвращаем максимальную дистанцию
            return maxRaycastDistance;
        }
    }
    
    Vector3 CalculateLeadPoint(Vector3 targetPosition)
    {
        // Получаем цель и её скорость
        GameObject[] enemies = GameObject.FindGameObjectsWithTag("AirEnemy");
        Rigidbody targetRigidbody = null;
        
        foreach (GameObject enemy in enemies)
        {
            if (Vector3.Distance(enemy.transform.position, targetPosition) < 10f)
            {
                targetRigidbody = enemy.GetComponent<Rigidbody>();
                break;
            }
        }
        
        if (targetRigidbody == null)
            return targetPosition;
            
        // Получаем скорость цели
        Vector3 targetVelocity = targetRigidbody.linearVelocity;
        
        // Рассчитываем дистанцию до цели
        float distanceToTarget = Vector3.Distance(gunMuzzle.position, targetPosition);
        
        // Время полета снаряда
        float timeToTarget = distanceToTarget / projectileSpeed;
        
        // Точка упреждения = позиция цели + скорость цели * время полета
        Vector3 leadPoint = targetPosition + targetVelocity * timeToTarget;
        
        return leadPoint;
    }
    
    // Публичный метод для получения текущей точки прицеливания
    public Vector3 GetCurrentAimPoint()
    {
        return currentAimPointWorld;
    }
    
    // Публичный метод для получения дистанции до точки прицеливания
    public float GetCurrentAimDistance()
    {
        return currentAimDistance;
    }
    
    // Метод для настройки масштаба прицела
    public void SetSightScale(float scale)
    {
        sightScale = scale;
        if (rectTransform != null)
        {
            rectTransform.localScale = Vector3.one * sightScale;
        }
    }
    
    // Метод для отображения/скрытия прицела
    public void SetSightVisible(bool visible)
    {
        if (sightImage != null)
        {
            sightImage.enabled = visible;
        }
    }
}