SummerGame/Assets/Scripts/CameraController.cs

198 lines
8.0 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;
public class CameraController : MonoBehaviour
{
[Header("Настройки позиции камеры (Зум)")]
public float distance = 10f;
public float minDistance = 3f;
public float maxDistance = 30f;
public float zoomSpeed = 0.05f;
[Header("Настройки цели (Ось Y)")]
public float targetY = 0f;
public float minTargetY = 0f;
public float maxTargetY = 15f;
public float moveTargetSpeed = 0.02f;
public float addingHeight = 3f;
[Header("Настройки вращения")]
public float rotationSpeed = 0.2f;
[SerializeField]
private float currentAngle = -45f;
[Header("Настройки смещения (Pan - НОВОЕ)")]
[Tooltip("Скорость смещения камеры по горизонтали")]
public float panSpeed = 0.03f;
[Tooltip("При каком отдалении камеры разрешено смещение? (Если отдалить дальше - смещение сбросится)")]
public float zoomThresholdForPan = 15f;
[Tooltip("Максимальное смещение от центра комнаты")]
public float maxPanDistance = 10f;
[Header("Настройки плавности (Сглаживание)")]
[Range(0.01f, 0.5f)]
public float smoothTime = 0.1f;
public float touchDeadZone = 1.5f;
// ЦЕЛЕВЫЕ значения
private float _targetAngle;
private float _targetY;
private float _targetDistance;
// НОВОЕ: Целевое и текущее смещение по осям X и Z
private Vector2 _targetPanOffset;
private Vector2 _currentPanOffset;
// Внутренние переменные скорости для SmoothDamp
private float _angleVelocity;
private float _yVelocity;
private float _distanceVelocity;
private Vector2 _panVelocity; // Скорость для смещения
void Start()
{
_targetAngle = currentAngle;
_targetY = targetY;
_targetDistance = distance;
_targetPanOffset = Vector2.zero;
_currentPanOffset = Vector2.zero;
UpdateCameraPosition();
}
void LateUpdate()
{
HandleInput();
CheckPanReset(); // Проверяем, не пора ли сбросить смещение
SmoothMovement();
UpdateCameraPosition();
}
private void HandleInput()
{
// === 1. УПРАВЛЕНИЕ ОДНИМ ПАЛЬЦЕМ (Вращение и высота) ===
if (Input.touchCount == 1)
{
Touch touch = Input.GetTouch(0);
if (touch.phase == TouchPhase.Moved && touch.deltaPosition.sqrMagnitude > touchDeadZone * touchDeadZone)
{
_targetAngle += touch.deltaPosition.x * rotationSpeed;
_targetY -= touch.deltaPosition.y * moveTargetSpeed;
_targetY = Mathf.Clamp(_targetY, minTargetY, maxTargetY);
}
}
// === 2. УПРАВЛЕНИЕ ДВУМЯ ПАЛЬЦАМИ (Зум и Смещение) ===
else if (Input.touchCount == 2)
{
Touch touch0 = Input.GetTouch(0);
Touch touch1 = Input.GetTouch(1);
// -- Логика Зума --
Vector2 touch0PrevPos = touch0.position - touch0.deltaPosition;
Vector2 touch1PrevPos = touch1.position - touch1.deltaPosition;
float prevMagnitude = (touch0PrevPos - touch1PrevPos).magnitude;
float currentMagnitude = (touch0.position - touch1.position).magnitude;
float difference = currentMagnitude - prevMagnitude;
if (Mathf.Abs(difference) > touchDeadZone)
{
_targetDistance -= difference * zoomSpeed;
_targetDistance = Mathf.Clamp(_targetDistance, minDistance, maxDistance);
}
// -- НОВОЕ: Логика смещения (Панорамирование) --
// Разрешаем смещение только если камера достаточно близко
if (_targetDistance <= zoomThresholdForPan)
{
// Берем среднее движение двух пальцев
Vector2 avgDelta = (touch0.deltaPosition + touch1.deltaPosition) / 2f;
ApplyPan(avgDelta.x, avgDelta.y);
}
}
// === 3. МЫШЬ (Для редактора ПК) ===
else
{
// Левая кнопка - Вращение и высота
if (Input.GetMouseButton(0))
{
_targetAngle += Input.GetAxis("Mouse X") * rotationSpeed * 20f;
_targetY -= Input.GetAxis("Mouse Y") * moveTargetSpeed * 20f;
_targetY = Mathf.Clamp(_targetY, minTargetY, maxTargetY);
}
// НОВОЕ: Правая кнопка - Смещение (Pan)
else if (Input.GetMouseButton(1) && _targetDistance <= zoomThresholdForPan)
{
ApplyPan(Input.GetAxis("Mouse X") * 20f, Input.GetAxis("Mouse Y") * 20f);
}
// Зум колесиком мыши
float scroll = Input.GetAxis("Mouse ScrollWheel");
if (scroll != 0)
{
_targetDistance -= scroll * zoomSpeed * 100f;
_targetDistance = Mathf.Clamp(_targetDistance, minDistance, maxDistance);
}
}
}
// НОВЫЙ МЕТОД: Применение смещения относительно текущего поворота камеры
private void ApplyPan(float deltaX, float deltaY)
{
// Высчитываем векторы "вправо" и "вперед" для камеры, игнорируя наклон (ось Y)
Vector3 right = transform.right;
right.y = 0;
right.Normalize();
Vector3 forward = transform.forward;
forward.y = 0;
forward.Normalize();
// Умножаем движение пальца/мыши на направление камеры
Vector3 move = (right * -deltaX) + (forward * -deltaY);
_targetPanOffset += new Vector2(move.x, move.z) * panSpeed;
// Ограничиваем максимальное смещение, чтобы не улететь за карту
if (_targetPanOffset.magnitude > maxPanDistance)
{
_targetPanOffset = _targetPanOffset.normalized * maxPanDistance;
}
}
// НОВЫЙ МЕТОД: Сброс смещения при отдалении
private void CheckPanReset()
{
if (_targetDistance > zoomThresholdForPan)
{
// Если отдалились слишком сильно - обнуляем целевое смещение.
// Благодаря SmoothDamp камера вернется в центр плавно!
_targetPanOffset = Vector2.zero;
}
}
private void SmoothMovement()
{
currentAngle = Mathf.SmoothDamp(currentAngle, _targetAngle, ref _angleVelocity, smoothTime);
targetY = Mathf.SmoothDamp(targetY, _targetY, ref _yVelocity, smoothTime);
distance = Mathf.SmoothDamp(distance, _targetDistance, ref _distanceVelocity, smoothTime);
// НОВОЕ: Плавно сглаживаем позицию смещения
_currentPanOffset = Vector2.SmoothDamp(_currentPanOffset, _targetPanOffset, ref _panVelocity, smoothTime);
}
private void UpdateCameraPosition()
{
// НОВОЕ: Теперь цель вращения учитывает наше смещение по осям X и Z
Vector3 targetPoint = new Vector3(_currentPanOffset.x, targetY, _currentPanOffset.y);
float radians = currentAngle * Mathf.Deg2Rad;
float x = targetPoint.x + distance * Mathf.Sin(radians);
float z = targetPoint.z + distance * Mathf.Cos(radians);
transform.position = new Vector3(x, targetY + addingHeight, z);
transform.LookAt(targetPoint);
}
}