using UnityEngine; namespace EE2Clone.Hybrid { /// /// RTS-style camera controller. Supports WASD/arrow pan, edge-of-screen pan, /// scroll zoom, and Q/E rotation. Client-side only (MonoBehaviour). /// public class RTSCameraController : MonoBehaviour { [Header("Movement")] [SerializeField] private float panSpeed = 30f; [SerializeField] private float edgePanThreshold = 15f; [SerializeField] private bool enableEdgePan = true; [Header("Zoom")] [SerializeField] private float zoomSpeed = 10f; [SerializeField] private float minZoomHeight = 10f; [SerializeField] private float maxZoomHeight = 80f; [Header("Rotation")] [SerializeField] private float rotateSpeed = 100f; [Header("Bounds")] [SerializeField] private Vector2 mapMin = new(-128f, -128f); [SerializeField] private Vector2 mapMax = new(128f, 128f); private Transform _cameraTransform; private void Awake() { _cameraTransform = transform; } private void LateUpdate() { var input = RTSInputActions.Instance; if (input == null) return; HandlePan(input); HandleZoom(input); HandleRotation(input); ClampPosition(); } private void HandlePan(RTSInputActions input) { var panInput = input.CameraPan; var panDir = new Vector3(panInput.x, 0f, panInput.y); // Edge-of-screen panning if (enableEdgePan) { var mousePos = input.MousePosition; if (mousePos.x <= edgePanThreshold) panDir.x -= 1f; if (mousePos.x >= Screen.width - edgePanThreshold) panDir.x += 1f; if (mousePos.y <= edgePanThreshold) panDir.z -= 1f; if (mousePos.y >= Screen.height - edgePanThreshold) panDir.z += 1f; } if (panDir.sqrMagnitude > 0.01f) { panDir.Normalize(); // Move relative to camera's forward (ignoring Y) var forward = _cameraTransform.forward; forward.y = 0f; forward.Normalize(); var right = _cameraTransform.right; right.y = 0f; right.Normalize(); var move = (forward * panDir.z + right * panDir.x) * (panSpeed * Time.unscaledDeltaTime); _cameraTransform.position += move; } } private void HandleZoom(RTSInputActions input) { var zoomInput = input.CameraZoom; if (Mathf.Abs(zoomInput) > 0.01f) { var pos = _cameraTransform.position; pos.y -= zoomInput * zoomSpeed * Time.unscaledDeltaTime; pos.y = Mathf.Clamp(pos.y, minZoomHeight, maxZoomHeight); _cameraTransform.position = pos; } } private void HandleRotation(RTSInputActions input) { var rotateInput = input.CameraRotate; if (Mathf.Abs(rotateInput) > 0.01f) { _cameraTransform.Rotate(Vector3.up, rotateInput * rotateSpeed * Time.unscaledDeltaTime, Space.World); } } private void ClampPosition() { var pos = _cameraTransform.position; pos.x = Mathf.Clamp(pos.x, mapMin.x, mapMax.x); pos.z = Mathf.Clamp(pos.z, mapMin.y, mapMax.y); _cameraTransform.position = pos; } } }