using UnityEngine; using UnityEngine.InputSystem; /// /// Simple camera movement controller for map navigation. /// Supports WASD/arrow keys, right-click drag, and Q/E or mouse wheel zoom. /// [RequireComponent(typeof(Camera))] public class MazeCameraController : MonoBehaviour { [Header("Movement")] [SerializeField] private float moveSpeed = 20f; [SerializeField] private float dragSpeed = 1f; [Header("Zoom")] [SerializeField] private float zoomSpeed = 25f; [SerializeField] private float zoomMin = 5f; [SerializeField] private float zoomMax = 120f; [Header("Optional Bounds")] [SerializeField] private bool useBounds = false; [SerializeField] private Vector2 minBounds = new Vector2(-100f, -100f); [SerializeField] private Vector2 maxBounds = new Vector2(100f, 100f); private Camera cameraComponent; private Vector3 targetPosition; private Vector3 lastMousePosition; private bool isDragging; private void Awake() { cameraComponent = GetComponent(); targetPosition = transform.position; } private void Update() { HandleKeyboardMovement(); HandleMouseDrag(); HandleZoom(); ApplyPosition(); } private void HandleKeyboardMovement() { var keyboard = Keyboard.current; if (keyboard == null) { return; } float horizontal = 0f; if (keyboard.aKey.isPressed || keyboard.leftArrowKey.isPressed) { horizontal -= 1f; } if (keyboard.dKey.isPressed || keyboard.rightArrowKey.isPressed) { horizontal += 1f; } float vertical = 0f; if (keyboard.sKey.isPressed || keyboard.downArrowKey.isPressed) { vertical -= 1f; } if (keyboard.wKey.isPressed || keyboard.upArrowKey.isPressed) { vertical += 1f; } if (horizontal != 0f || vertical != 0f) { Vector3 right = transform.right; Vector3 forward = Vector3.Cross(transform.right, Vector3.up).normalized; Vector3 worldMove = (right * horizontal + forward * vertical).normalized; targetPosition += worldMove * moveSpeed * Time.deltaTime; } if (keyboard.qKey.isPressed) { Zoom(-zoomSpeed * Time.deltaTime); } else if (keyboard.eKey.isPressed) { Zoom(zoomSpeed * Time.deltaTime); } } private void HandleMouseDrag() { var mouse = Mouse.current; if (mouse == null) { return; } if (mouse.rightButton.wasPressedThisFrame) { isDragging = true; Vector2 position = mouse.position.ReadValue(); lastMousePosition = new Vector3(position.x, position.y, 0f); } if (mouse.rightButton.wasReleasedThisFrame) { isDragging = false; } if (isDragging && mouse.rightButton.isPressed) { Vector2 position = mouse.position.ReadValue(); Vector3 currentMousePosition = new Vector3(position.x, position.y, 0f); if (currentMousePosition != lastMousePosition) { Vector3 dragDelta = GetDragWorldDelta(lastMousePosition, currentMousePosition); targetPosition += dragDelta * dragSpeed; lastMousePosition = currentMousePosition; } } } private void HandleZoom() { var mouse = Mouse.current; if (mouse != null) { float scroll = mouse.scroll.ReadValue().y; if (scroll != 0f) { Zoom(-scroll * zoomSpeed * Time.deltaTime); } } } private void Zoom(float amount) { if (cameraComponent.orthographic) { cameraComponent.orthographicSize = Mathf.Clamp(cameraComponent.orthographicSize + amount, zoomMin, zoomMax); } else { cameraComponent.fieldOfView = Mathf.Clamp(cameraComponent.fieldOfView + amount, zoomMin, zoomMax); } } private Vector3 GetDragWorldDelta(Vector3 previousScreenPosition, Vector3 currentScreenPosition) { Plane dragPlane = new Plane(-transform.forward, transform.position); Ray previousRay = cameraComponent.ScreenPointToRay(previousScreenPosition); Ray currentRay = cameraComponent.ScreenPointToRay(currentScreenPosition); if (dragPlane.Raycast(previousRay, out float previousDistance) && dragPlane.Raycast(currentRay, out float currentDistance)) { Vector3 previousWorld = previousRay.GetPoint(previousDistance); Vector3 currentWorld = currentRay.GetPoint(currentDistance); return previousWorld - currentWorld; } return Vector3.zero; } private void ApplyPosition() { Vector3 newPosition = targetPosition; if (useBounds) { newPosition.x = Mathf.Clamp(newPosition.x, minBounds.x, maxBounds.x); newPosition.z = Mathf.Clamp(newPosition.z, minBounds.y, maxBounds.y); } transform.position = newPosition; } }