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


using UnityEngine;

public class SoftVehicleCamera : MonoBehaviour
{
    [Header("Ссылки")]
    [SerializeField] private Transform target;
    [SerializeField] private Rigidbody vehicleRigidbody;
    [SerializeField] private Transform gun;

    [Header("Дистанция и Позиция")]
    [SerializeField] private float distance = 5.0f;
    [SerializeField] private float height = 1.5f;
    
    [Header("Мягкость и Сглаживание")]
    [SerializeField] private float rotationSmoothTime = 0.3f;
    [SerializeField] private float angleThreshold = 15.0f;

    [Header("Вращение мыши")]
    [SerializeField] private float mouseSensitivity = 3.0f;
    [SerializeField] private float minPitch = -30f;
    [SerializeField] private float maxPitch = 60f;

    [Header("Смещение прицела")]
    [SerializeField] private float aimOffsetSensitivity = 3.0f;
    [SerializeField] private float maxAimOffsetDegrees = 10f;

    private float horizontalAngle = 0f;
    private float verticalAngle = 15f;
    private float currentDistance = 5f;
    
    private float smoothHorizontalVelocity;
    private Vector3 smoothPositionVelocity;
    
    private bool followGunMode = false;
    
    private Vector2 lockedTargetOffsetAngles = Vector2.zero;
    private float baseHorizontalAngle = 0f;
    private float baseVerticalAngle = 0f;

    void Start()
    {
        if (target == null) return;
        
        Vector3 direction = (transform.position - target.position).normalized;
        horizontalAngle = Mathf.Atan2(direction.x, direction.z) * Mathf.Rad2Deg;
        verticalAngle = Mathf.Asin(direction.y) * Mathf.Rad2Deg;
        verticalAngle = Mathf.Clamp(verticalAngle, minPitch, maxPitch);
        currentDistance = Vector3.Distance(transform.position, target.position);
    }

    void LateUpdate()
    {
        if (!target) return;

        if (followGunMode && gun != null)
        {
            HandleFollowGunMode();
            
            // Сохраняем текущие углы камеры
            UpdateCameraAnglesFromPosition();
        }
        else
        {
            HandleManualMode();
        }
    }

    void HandleManualMode()
    {
        // Ввод с мыши
        if (Input.GetMouseButton(0))
        {
            float mouseX = Input.GetAxis("Mouse X") * mouseSensitivity * 10f;
            horizontalAngle += mouseX;
            
            float mouseY = Input.GetAxis("Mouse Y") * mouseSensitivity * 10f;
            verticalAngle = Mathf.Clamp(verticalAngle - mouseY, minPitch, maxPitch);
        }

        // УБРАНО: Автоматическое следование за машиной при движении
        // Камера больше не поворачивается автоматически

        // Позиция камеры
        Quaternion rotation = Quaternion.Euler(verticalAngle, horizontalAngle, 0f);
        Vector3 direction = rotation * Vector3.back;
        
        Vector3 desiredPosition = target.position + direction * currentDistance;
        desiredPosition.y = target.position.y + height + Mathf.Sin(verticalAngle * Mathf.Deg2Rad) * currentDistance * 0.3f;

        transform.position = Vector3.SmoothDamp(transform.position, desiredPosition, ref smoothPositionVelocity, 0.08f);
        transform.LookAt(target.position + Vector3.up * 0.5f);
    }

    void HandleFollowGunMode()
    {
        Vector3 gunForward = gun.forward;
        Vector3 gunPosition = gun.position;
        
        if (PantsirRadarSystem.IsAnyTargetLocked && PantsirRadarSystem.LockedTargetPosition.HasValue)
        {
            Vector3 lockedTargetPos = PantsirRadarSystem.LockedTargetPosition.Value;
            
            Vector3 directionToTarget = (lockedTargetPos - gunPosition).normalized;
            baseHorizontalAngle = Mathf.Atan2(directionToTarget.x, directionToTarget.z) * Mathf.Rad2Deg;
            baseVerticalAngle = Mathf.Asin(directionToTarget.y) * Mathf.Rad2Deg;
            baseVerticalAngle = Mathf.Clamp(baseVerticalAngle, minPitch, maxPitch);
            
            if (Input.GetMouseButton(0))
            {
                float mouseX = Input.GetAxis("Mouse X") * aimOffsetSensitivity;
                float mouseY = Input.GetAxis("Mouse Y") * aimOffsetSensitivity;
                
                lockedTargetOffsetAngles += new Vector2(mouseX, mouseY);
                lockedTargetOffsetAngles = Vector2.ClampMagnitude(lockedTargetOffsetAngles, maxAimOffsetDegrees);
            }
            
            float finalHorizontalAngle = baseHorizontalAngle + lockedTargetOffsetAngles.x;
            float finalVerticalAngle = Mathf.Clamp(
                baseVerticalAngle + lockedTargetOffsetAngles.y, 
                minPitch, 
                maxPitch
            );
            
            PantsirRadarSystem.AimOffset = lockedTargetOffsetAngles;
            
            Quaternion gunRotation = Quaternion.Euler(finalVerticalAngle, finalHorizontalAngle, 0f);
            Vector3 cameraDirection = gunRotation * Vector3.back;
            
            Vector3 desiredPosition = gunPosition + cameraDirection * distance;
            desiredPosition.y = gunPosition.y + height + Mathf.Sin(finalVerticalAngle * Mathf.Deg2Rad) * distance * 0.3f;
            
            transform.position = Vector3.SmoothDamp(transform.position, desiredPosition, ref smoothPositionVelocity, 0.08f);
            
            Vector3 aimPoint = lockedTargetPos;
            Quaternion offsetRotation = Quaternion.Euler(
                lockedTargetOffsetAngles.y, 
                lockedTargetOffsetAngles.x, 
                0f
            );
            Vector3 offsetDirection = offsetRotation * directionToTarget;
            aimPoint = gunPosition + offsetDirection * Vector3.Distance(gunPosition, lockedTargetPos);
            
            transform.LookAt(aimPoint);
            PantsirRadarSystem.AimPoint = aimPoint;
        }
        else
        {
            if (Input.GetMouseButton(0))
            {
                float mouseX = Input.GetAxis("Mouse X") * mouseSensitivity * 10f;
                horizontalAngle += mouseX;
                
                float mouseY = Input.GetAxis("Mouse Y") * mouseSensitivity * 10f;
                verticalAngle = Mathf.Clamp(verticalAngle - mouseY, minPitch, maxPitch);
            }
            
            Vector3 desiredPosition = gunPosition - gunForward * distance + Vector3.up * height;
            transform.position = Vector3.SmoothDamp(transform.position, desiredPosition, ref smoothPositionVelocity, 0.08f);
            transform.LookAt(gunPosition + gunForward * 1000f);
        }
    }

    // Метод для сохранения текущих углов камеры
    private void UpdateCameraAnglesFromPosition()
    {
        Vector3 directionFromTarget = (transform.position - target.position).normalized;
        
        horizontalAngle = Mathf.Atan2(directionFromTarget.x, directionFromTarget.z) * Mathf.Rad2Deg;
        verticalAngle = Mathf.Asin(directionFromTarget.y) * Mathf.Rad2Deg;
        verticalAngle = Mathf.Clamp(verticalAngle, minPitch, maxPitch);
        currentDistance = Vector3.Distance(transform.position, target.position);
    }

    public void SetFollowMode(bool enable)
    {
        followGunMode = enable;
        
        lockedTargetOffsetAngles = Vector2.zero;
        PantsirRadarSystem.AimOffset = Vector2.zero;
    }

    public void RotateToTarget(Vector3 targetPosition)
    {
        lockedTargetOffsetAngles = Vector2.zero;
        
        if (gun != null)
        {
            Vector3 directionToTarget = (targetPosition - gun.position).normalized;
            
            baseHorizontalAngle = Mathf.Atan2(directionToTarget.x, directionToTarget.z) * Mathf.Rad2Deg;
            baseVerticalAngle = Mathf.Asin(directionToTarget.y) * Mathf.Rad2Deg;
            baseVerticalAngle = Mathf.Clamp(baseVerticalAngle, minPitch, maxPitch);
            
            Vector3 gunPosition = gun.position;
            Quaternion rotation = Quaternion.Euler(baseVerticalAngle, baseHorizontalAngle, 0f);
            Vector3 cameraDirection = rotation * Vector3.back;
            
            transform.position = gunPosition + cameraDirection * distance;
            transform.position += Vector3.up * height;
            
            transform.LookAt(targetPosition);
        }
        else
        {
            transform.LookAt(targetPosition);
        }
        
        PantsirRadarSystem.AimOffset = Vector2.zero;
    }

    public void ResetAimOffset()
    {
        followGunMode = false;
        lockedTargetOffsetAngles = Vector2.zero;
        PantsirRadarSystem.AimOffset = Vector2.zero;

        // Считаем углы напрямую из НАПРАВЛЕНИЯ ВЗГЛЯДА камеры, а не из её позиции
        Vector3 forwardDir = transform.forward;

        // Рассчитываем горизонтальный угол (куда смотрим по горизонтали)
        horizontalAngle = Mathf.Atan2(forwardDir.x, forwardDir.z) * Mathf.Rad2Deg;

        // Рассчитываем вертикальный угол (наклон)
        // Инвертируем знак, так как forwardDir.y направлен вверх, а в HandleManualMode угол вычитается
        verticalAngle = -Mathf.Asin(forwardDir.y) * Mathf.Rad2Deg;
        verticalAngle = Mathf.Clamp(verticalAngle, minPitch, maxPitch);

        if (target != null)
        {
            // Фиксируем текущую дистанцию до цели
            currentDistance = Vector3.Distance(transform.position, target.position);
        }
    }

    public Vector3 GetAimPoint()
    {
        Ray ray = new Ray(transform.position, transform.forward);
        float maxDistance = 10000f;
        RaycastHit hit;
        
        if (Physics.Raycast(ray, out hit, maxDistance))
        {
            return hit.point;
        }
        
        return transform.position + transform.forward * maxDistance;
    }

    public bool IsInFollowMode()
    {
        return followGunMode;
    }
}