using System.Collections; using System.Collections.Generic; using UnityEngine; public class CameraController : MonoBehaviour { [Header("Refs")] public Transform pivot; // если не задан — возьмём свой transform public GameManager gameManager; // чтобы блокировать в UI public Transform shipPlacementCameraPosition; public Transform mainMenuCameraPosition; public Transform gameplayCameraPosition; [Header("Input")] public ButtonPinMapping rotateLeftKey; public ButtonPinMapping rotateRightKey; [Header("Speeds")] public float rotateSpeed = 90f; // ручное вращение public float returnSpeed = 120; // возврат в "домой" private Quaternion _homeRotation; private float _turnHoldTime = 0f; [Tooltip("Секунд удержания до включения вращения камеры")] public float turnHoldThreshold = 0.3f; public float cameraMoveDuration = 1.0f; // Время перемещения в секундах private int countDown = 0; private float lastTapTime = 0f; [Tooltip("Окно времени для распознавания двойного нажатия (сек)")] public float doubleTapWindow = 0.4f; private bool isReturning = false; [Tooltip("Центр вращения камеры во время расстановки кораблей (пустой GO у поля игрока)")] [SerializeField] private Transform shipPlacementPivotPoint; /// Исходная мировая позиция cameraPivot — восстанавливается вне режима расстановки. private Vector3 _defaultPivotPosition; public void CaptureHomeNow() => _homeRotation = pivot.rotation; void Awake() { if (!pivot) pivot = transform; // по умолчанию "дом" — текущий поворот на старте _homeRotation = this.transform.rotation; } void Start() { if (pivot != null) _defaultPivotPosition = pivot.position; } void Update() { float dir = 0f; // задержка при расстановке кораблей if (gameManager.currentState == GameState.ShipPlacement) { if (In.GetButton(rotateLeftKey) || In.GetButton(rotateRightKey)) { _turnHoldTime += Time.deltaTime; if (_turnHoldTime < turnHoldThreshold) return; if (In.GetButton(rotateRightKey)) { dir -= 1f; } if (In.GetButton(rotateLeftKey)) { dir += 1f; } if (dir != 0f && pivot) pivot.Rotate(Vector3.up, dir * rotateSpeed * Time.deltaTime, Space.World); return; } else _turnHoldTime = 0f; } if(gameManager != null && (gameManager.currentInputMode == GameManager.InputMode.UI || gameManager.currentInputMode == GameManager.InputMode.Settings)) return; // Обнаружение двойного нажатия (time-window) if (In.GetButtonDown(rotateLeftKey) || In.GetButtonDown(rotateRightKey)) { if (Time.time - lastTapTime <= doubleTapWindow) { countDown++; } else { countDown = 1; } lastTapTime = Time.time; if (countDown >= 2) { isReturning = true; countDown = 0; } } // Если в режиме возврата — двигаем камеру к дому if (isReturning) { pivot.rotation = Quaternion.RotateTowards(pivot.rotation, _homeRotation, returnSpeed * Time.deltaTime); if (Quaternion.Angle(pivot.rotation, _homeRotation) < 0.01f) { // Vector3 dir = pivot.rotation.eulerAngles; // if (targetCursor != null) targetCursor.SwitchButton(dir); isReturning = false; } } if (In.GetButton(rotateRightKey)) { dir -= 1f; } if (In.GetButton(rotateLeftKey)) { dir += 1f; } if (dir != 0f && pivot) pivot.Rotate(Vector3.up, dir * rotateSpeed * Time.deltaTime, Space.World); } public void MoveCameraToMainMenu() => MoveCameraTo(mainMenuCameraPosition); public void MoveCameraToShipPlacement() => MoveCameraTo(shipPlacementCameraPosition); public void MoveCameraToGameplay() => MoveCameraTo(gameplayCameraPosition); public void MoveCameraTo(Transform target) { if (target != null) { StopAllCoroutines(); StartCoroutine(MoveCameraSmoothly(target)); } } private IEnumerator MoveCameraSmoothly(Transform target) { Transform cam = this.transform; // Отсоединяем камеру от пивота на время перемещения — // иначе поворот пивота кнопками во время полёта камеры сдвигает её конечную позицию cam.SetParent(null); Vector3 startPos = cam.position; Quaternion startRot = cam.rotation; Vector3 endPos = target.position; Quaternion endRot = target.rotation; float elapsed = 0f; while (elapsed < cameraMoveDuration) { float t = elapsed / cameraMoveDuration; cam.position = Vector3.Lerp(startPos, endPos, t); cam.rotation = Quaternion.Slerp(startRot, endRot, t); elapsed += Time.deltaTime; yield return null; } cam.position = endPos; cam.rotation = endRot; // Сбрасываем пивот и возвращаем камеру обратно как дочерний объект if (pivot != null) { pivot.rotation = Quaternion.identity; // Перемещаем пивот: во время расстановки кораблей — к полю игрока, // в остальных состояниях — обратно на дефолтную позицию bool isShipPlacement = (target == shipPlacementCameraPosition); if (isShipPlacement && shipPlacementPivotPoint != null) pivot.position = shipPlacementPivotPoint.position; else pivot.position = _defaultPivotPosition; // worldPositionStays: true — локальные координаты пересчитаются под новый пивот cam.SetParent(pivot, true); CaptureHomeNow(); } } }