Files
EE2Clone/Assets/Scripts/Hybrid/RTSCameraController.cs
ldbetteridge 58da5d1d71 Initial import
2026-03-31 15:59:23 +01:00

107 lines
3.5 KiB
C#

using UnityEngine;
namespace EE2Clone.Hybrid
{
/// <summary>
/// RTS-style camera controller. Supports WASD/arrow pan, edge-of-screen pan,
/// scroll zoom, and Q/E rotation. Client-side only (MonoBehaviour).
/// </summary>
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;
}
}
}