Initial commit
This commit is contained in:
148
Assets/Scripts/MapCameraController.cs
Normal file
148
Assets/Scripts/MapCameraController.cs
Normal file
@@ -0,0 +1,148 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user