Files
XuisosukeStrategy/Assets/Scripts/MapCameraController.cs
2026-04-05 12:39:21 +03:00

149 lines
6.1 KiB
C#
Raw Permalink 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;
[RequireComponent(typeof(Camera))]
public class MapCameraController : MonoBehaviour
{
[Header("Настройки карты")]
[Tooltip("Ссылка на SpriteRenderer вашей карты для определения границ")]
public SpriteRenderer mapRenderer;
[Header("Настройки перемещения")]
[Tooltip("Скорость перемещения камеры")]
public float panSpeed = 15f;
[Header("Настройки зума")]
[Tooltip("Скорость приближения/отдаления")]
public float zoomSpeed = 20f;
[Tooltip("Максимальное приближение (минимальный orthographic size)")]
public float minZoom = 2f;
[Tooltip("Максимальное отдаление (рассчитывается автоматически при старте)")]
public float maxZoom = 10f;
private Camera cam;
private void Awake()
{
cam = GetComponent<Camera>();
if (!cam.orthographic)
{
Debug.LogWarning("Камера должна быть Orthographic (ортографической) для 2D стратегии!");
cam.orthographic = true;
}
}
private void Start()
{
if (mapRenderer != null)
{
// Рассчитываем максимальное отдаление так, чтобы камера не могла стать больше самой карты
CalculateMaxZoom();
}
else
{
Debug.LogWarning("Не назначен mapRenderer в MapCameraController! Привяжите спрайт карты в инспекторе.");
}
}
private void Update()
{
HandleZoom();
HandleMovement();
}
private void CalculateMaxZoom()
{
float mapHeight = mapRenderer.bounds.size.y;
float mapWidth = mapRenderer.bounds.size.x;
// orthographicSize — это половина высоты камеры.
// Считаем максимально возможные размеры камеры, чтобы не выходить за границы карты.
float maxZoomY = mapHeight / 2f;
float maxZoomX = (mapWidth / 2f) / cam.aspect;
// Берем минимальное из двух значений, чтобы зум останавливался, когда любая из сторон карты полностью влезает в экран
maxZoom = Mathf.Min(maxZoomY, maxZoomX);
// Если текущий зум больше возможного, поправляем его
cam.orthographicSize = Mathf.Clamp(cam.orthographicSize, minZoom, maxZoom);
}
private void HandleZoom()
{
float zoomChange = 0f;
// Клавиши приближения (KeypadPlus = Num+, Equals/Plus = обычный +)
if (Input.GetKey(KeyCode.KeypadPlus) || Input.GetKey(KeyCode.Equals) || Input.GetKey(KeyCode.Plus))
{
zoomChange -= zoomSpeed * Time.deltaTime;
}
// Клавиши отдаления (KeypadMinus = Num-, Minus = обычный -)
if (Input.GetKey(KeyCode.KeypadMinus) || Input.GetKey(KeyCode.Minus))
{
zoomChange += zoomSpeed * Time.deltaTime;
}
// Также добавляем возможность зума на колесико мыши (полезно в стратегиях)
float scrollInput = Input.GetAxisRaw("Mouse ScrollWheel");
if (Mathf.Abs(scrollInput) > 0.01f)
{
zoomChange -= scrollInput * zoomSpeed * 5f; // Умножаем, так как колесико дает маленькие значения
}
if (Mathf.Abs(zoomChange) > 0.001f)
{
cam.orthographicSize = Mathf.Clamp(cam.orthographicSize + zoomChange, minZoom, maxZoom);
// Если изменился размер экрана, нужно пересчитать центрирование, что сделает функция HandleMovement
}
}
private void HandleMovement()
{
if (mapRenderer == null) return;
// Получаем ввод для осей (по умолчанию в Unity Horizontal — это A, D, LeftArrow, RightArrow; Vertical — W, S, UpArrow, DownArrow)
float horizontal = Input.GetAxisRaw("Horizontal");
float vertical = Input.GetAxisRaw("Vertical");
Vector3 moveDirection = new Vector3(horizontal, vertical, 0f).normalized;
Vector3 targetPosition = transform.position + moveDirection * panSpeed * Time.deltaTime;
// Вычисляем текущие размеры камеры
float camHalfHeight = cam.orthographicSize;
float camHalfWidth = cam.orthographicSize * cam.aspect;
Bounds mapBounds = mapRenderer.bounds;
// Вычисляем границы, за которые центр камеры не должен выходить
float minX = mapBounds.min.x + camHalfWidth;
float maxX = mapBounds.max.x - camHalfWidth;
float minY = mapBounds.min.y + camHalfHeight;
float maxY = mapBounds.max.y - camHalfHeight;
// Ограничиваем позицию по X.
// Если карта по ширине уже полностью влезает (minX > maxX), центрируем её
if (minX > maxX)
{
targetPosition.x = mapBounds.center.x;
}
else
{
targetPosition.x = Mathf.Clamp(targetPosition.x, minX, maxX);
}
// Аналогично ограничиваем по Y
if (minY > maxY)
{
targetPosition.y = mapBounds.center.y;
}
else
{
targetPosition.y = Mathf.Clamp(targetPosition.y, minY, maxY);
}
// Применяем позицию (оставляем Z как было)
targetPosition.z = transform.position.z;
transform.position = targetPosition;
}
}