using UnityEngine; public class CameraController : MonoBehaviour { [Header("Movement Settings")] [SerializeField] private float panSpeed = 5f; [SerializeField] private float zoomSpeed = 2f; [SerializeField] private float rotationSpeed = 100f; [Header("Limits")] [SerializeField] private float minZoom = 5f; [SerializeField] private float maxZoom = 50f; [SerializeField] private Vector2 panLimitX = new Vector2(-50f, 50f); [SerializeField] private Vector2 panLimitZ = new Vector2(-50f, 50f); [Header("Input Settings")] [SerializeField] private KeyCode panKey = KeyCode.LeftShift; [SerializeField] private KeyCode rotateKey = KeyCode.LeftAlt; private Camera cam; private Vector3 lastMousePosition; private bool isDragging = false; private void Start() { cam = GetComponent(); if (cam == null) { cam = Camera.main; } // Set initial camera position for hotel view transform.position = new Vector3(0, 15f, -20f); transform.rotation = Quaternion.Euler(45f, 0f, 0f); } private void Update() { HandleMovementInput(); HandleZoomInput(); HandleRotationInput(); } private void HandleMovementInput() { // WASD movement Vector3 movement = Vector3.zero; if (Input.GetKey(KeyCode.W)) movement += transform.forward; if (Input.GetKey(KeyCode.S)) movement -= transform.forward; if (Input.GetKey(KeyCode.A)) movement -= transform.right; if (Input.GetKey(KeyCode.D)) movement += transform.right; // Apply movement with speed adjustment based on camera height float speedMultiplier = transform.position.y / 10f; movement *= panSpeed * speedMultiplier * Time.deltaTime; // Clamp position within limits Vector3 newPosition = transform.position + movement; newPosition.x = Mathf.Clamp(newPosition.x, panLimitX.x, panLimitX.y); newPosition.z = Mathf.Clamp(newPosition.z, panLimitZ.x, panLimitZ.y); transform.position = newPosition; // Mouse drag panning HandleMousePanning(); } private void HandleMousePanning() { if (Input.GetMouseButtonDown(2) || (Input.GetMouseButtonDown(0) && Input.GetKey(panKey))) // Middle mouse or Shift+Left mouse { isDragging = true; lastMousePosition = Input.mousePosition; } else if (Input.GetMouseButtonUp(2) || Input.GetMouseButtonUp(0)) { isDragging = false; } if (isDragging) { Vector3 mouseDelta = Input.mousePosition - lastMousePosition; // Convert mouse movement to world movement Vector3 worldDelta = new Vector3(-mouseDelta.x, 0, -mouseDelta.y) * panSpeed * 0.01f; // Apply relative to camera orientation worldDelta = transform.TransformDirection(worldDelta); worldDelta.y = 0; // Keep camera at same height during panning Vector3 newPosition = transform.position + worldDelta; newPosition.x = Mathf.Clamp(newPosition.x, panLimitX.x, panLimitX.y); newPosition.z = Mathf.Clamp(newPosition.z, panLimitZ.x, panLimitZ.y); transform.position = newPosition; lastMousePosition = Input.mousePosition; } } private void HandleZoomInput() { float scroll = Input.GetAxis("Mouse ScrollWheel"); if (Mathf.Abs(scroll) > 0.01f) { // For orthographic camera, adjust orthographicSize if (cam.orthographic) { cam.orthographicSize -= scroll * zoomSpeed; cam.orthographicSize = Mathf.Clamp(cam.orthographicSize, minZoom, maxZoom); } else { // For perspective camera, move camera forward/backward Vector3 zoomDirection = transform.forward * scroll * zoomSpeed; Vector3 newPosition = transform.position + zoomDirection; // Limit zoom by height if (newPosition.y >= minZoom && newPosition.y <= maxZoom) { transform.position = newPosition; } } } } private void HandleRotationInput() { if (Input.GetMouseButton(1) || (Input.GetMouseButton(0) && Input.GetKey(rotateKey))) // Right mouse or Alt+Left mouse { float mouseX = Input.GetAxis("Mouse X") * rotationSpeed * Time.deltaTime; float mouseY = -Input.GetAxis("Mouse Y") * rotationSpeed * Time.deltaTime; // Rotate around Y axis (horizontal rotation) transform.Rotate(Vector3.up, mouseX, Space.World); // Rotate around local X axis (vertical rotation) transform.Rotate(Vector3.right, mouseY, Space.Self); // Clamp vertical rotation Vector3 eulerAngles = transform.eulerAngles; if (eulerAngles.x > 180f) eulerAngles.x -= 360f; eulerAngles.x = Mathf.Clamp(eulerAngles.x, -80f, 80f); transform.eulerAngles = eulerAngles; } } #region Public Methods public void FocusOnPosition(Vector3 position, float distance = 15f) { Vector3 direction = (transform.position - position).normalized; transform.position = position + direction * distance; transform.LookAt(position); } public void SetPanLimits(Vector2 xLimits, Vector2 zLimits) { panLimitX = xLimits; panLimitZ = zLimits; } public void ResetCamera() { transform.position = new Vector3(0, 15f, -20f); transform.rotation = Quaternion.Euler(45f, 0f, 0f); } #endregion private void OnDrawGizmosSelected() { // Draw pan limits Gizmos.color = Color.yellow; Vector3 center = new Vector3((panLimitX.x + panLimitX.y) / 2f, 0, (panLimitZ.x + panLimitZ.y) / 2f); Vector3 size = new Vector3(panLimitX.y - panLimitX.x, 1f, panLimitZ.y - panLimitZ.x); Gizmos.DrawWireCube(center, size); } }