Kursach_StealthAction/Assets/Scripts/CameraFollow.cs
2026-10-23 15:44:09 +03:00

123 lines
5.1 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using UnityEngine;
using UnityEngine.InputSystem;
public class CameraFollow : MonoBehaviour
{
[Header("За кем следить")]
public Transform target; // Ссылка на персонажа (Player)
[Header("Настройки дистанции и зума")]
[Tooltip("Текущая дистанция камеры от игрока")]
public float distance = 2.4f; // Было 4.0 -> теперь 2.4 (персонаж ближе и крупнее)
[Tooltip("Минимальное приближение при зуме колесиком мыши")]
public float minDistance = 1.6f;
[Tooltip("Максимальное отдаление при зуме колесиком мыши")]
public float maxDistance = 4.0f;
[Tooltip("Скорость зума колесиком мыши")]
public float zoomSpeed = 0.4f;
[Header("Позиционирование")]
[Tooltip("Высота камеры над игроком")]
public float height = 1.35f;
[Tooltip("Небольшое смещение вправо (плечевой вид от третьего лица)")]
public float shoulderOffset = 0.25f;
[Header("Настройки обзора (Мышь)")]
public float mouseSensitivity = 10f;
public float minPitch = -40f;
public float maxPitch = 60f;
[Header("Коллизия со стенами")]
[Tooltip("Предотвращает прохождение камеры сквозь стены бункера")]
public bool checkWallCollision = true;
public LayerMask collisionLayers = ~0;
public float collisionRadius = 0.2f;
private float pitch = 0f; // Вращение вверх/вниз (X)
private float yaw = 0f; // Вращение влево/вправо (Y)
private float currentDistance;
void Start()
{
Time.timeScale = 1f;
Vector3 angles = transform.eulerAngles;
pitch = angles.x;
yaw = angles.y;
currentDistance = distance;
if (target == null)
{
var player = GameObject.FindWithTag("Player");
if (player != null) target = player.transform;
}
// Исключаем слой Ignore Raycast (слой 2) из проверки стен
collisionLayers &= ~(1 << 2);
if (target != null)
{
Quaternion rot = Quaternion.Euler(pitch, yaw, 0f);
Vector3 targetFocus = target.position + (Vector3.up * height);
Vector3 rightOffset = rot * Vector3.right * shoulderOffset;
Vector3 desiredOrigin = targetFocus + rightOffset;
Vector3 backDir = -(rot * Vector3.forward);
transform.position = desiredOrigin + (backDir * distance);
transform.rotation = rot;
}
}
void LateUpdate()
{
if (target == null || Time.timeScale == 0f) return;
var mouse = Mouse.current;
if (mouse != null)
{
// Читаем дельту мыши (смещение курсора за один кадр)
Vector2 mouseDelta = mouse.delta.ReadValue();
float sens = mouseSensitivity * GameSettings.GetMouseSensitivity();
yaw += mouseDelta.x * sens * Time.deltaTime;
pitch -= mouseDelta.y * sens * Time.deltaTime;
// Ограничиваем угол наклона камеры
pitch = Mathf.Clamp(pitch, minPitch, maxPitch);
// Плавный зум колесиком мыши: игрок может сам отдалять/приближать камеру
float scroll = mouse.scroll.ReadValue().y;
if (Mathf.Abs(scroll) > 0.01f)
{
distance = Mathf.Clamp(distance - Mathf.Sign(scroll) * zoomSpeed, minDistance, maxDistance);
}
}
// Вращаем камеру
Quaternion rotation = Quaternion.Euler(pitch, yaw, 0f);
// Точка фокусировки над персонажем
Vector3 targetFocus = target.position + (Vector3.up * height);
// Плечевое смещение
Vector3 rightOffset = rotation * Vector3.right * shoulderOffset;
Vector3 desiredOrigin = targetFocus + rightOffset;
// Направление назад
Vector3 backDirection = -(rotation * Vector3.forward);
float targetDist = distance;
// Коллизия со стенами: не даем камере заглядывать сквозь стены
if (checkWallCollision)
{
if (Physics.SphereCast(targetFocus, collisionRadius, backDirection, out RaycastHit hit, distance, collisionLayers, QueryTriggerInteraction.Ignore))
{
targetDist = Mathf.Clamp(hit.distance - 0.1f, minDistance * 0.5f, distance);
}
}
currentDistance = Mathf.Lerp(currentDistance, targetDist, Time.deltaTime * 15f);
Vector3 position = desiredOrigin + (backDirection * currentDistance);
transform.position = position;
transform.rotation = rotation;
}
}