using UnityEngine; #if ENABLE_INPUT_SYSTEM using UnityEngine.InputSystem; #endif /// /// Orbit the tank with the mouse: drag to look around within a limited arc /// (so paper cards never go edge-on), scroll to zoom. Works with either the /// new Input System or the legacy Input manager. /// Tab toggles room mode: fly freely around the room (WASD / arrows to move, /// Q/E down/up, drag to look, scroll to move forward, Shift for speed). /// Tab again glides back to the tank view. /// public class TankOrbitCamera : MonoBehaviour { public Vector3 pivot = new Vector3(0f, 0f, 0f); public float distance = 16f; public Vector2 distanceRange = new Vector2(8f, 24f); [Header("Limits (degrees)")] public float yawLimit = 40f; public Vector2 pitchRange = new Vector2(-8f, 25f); [Header("Feel")] public float dragSensitivity = 0.25f; public float zoomSensitivity = 2f; public float smoothing = 8f; public bool dragWithLeftButton = true; [Header("Room mode (Tab)")] public float roomMoveSpeed = 40f; public float roomLookSensitivity = 2.5f; bool roomMode, returning; float roomYaw, roomPitch; float yaw, pitch, targetYaw, targetPitch, targetDistance; void Start() { targetDistance = distance; var cam = GetComponent(); if (cam != null) cam.farClipPlane = Mathf.Max(cam.farClipPlane, 3000f); // the room is scaled up; don't clip its far walls Vector3 dir = (transform.position - pivot).normalized; targetYaw = yaw = Mathf.Atan2(dir.x, -dir.z) * Mathf.Rad2Deg; targetPitch = pitch = Mathf.Asin(dir.y) * Mathf.Rad2Deg; Apply(); } void ReadMouse(out bool dragging, out Vector2 delta, out float scroll) { #if ENABLE_INPUT_SYSTEM var m = Mouse.current; if (m == null) { dragging = false; delta = Vector2.zero; scroll = 0f; return; } dragging = m.rightButton.isPressed || (dragWithLeftButton && m.leftButton.isPressed); delta = m.delta.ReadValue() * 0.1f; // roughly match legacy axis scale scroll = m.scroll.ReadValue().y / 120f; // wheel notches #else dragging = Input.GetMouseButton(1) || (dragWithLeftButton && Input.GetMouseButton(0)); delta = new Vector2(Input.GetAxis("Mouse X"), Input.GetAxis("Mouse Y")); scroll = Input.mouseScrollDelta.y; #endif } bool TabPressed() { #if ENABLE_INPUT_SYSTEM return Keyboard.current != null && Keyboard.current.tabKey.wasPressedThisFrame; #else return Input.GetKeyDown(KeyCode.Tab); #endif } Vector3 ReadMove(out bool fast) { float x = 0, y = 0, z = 0; #if ENABLE_INPUT_SYSTEM var k = Keyboard.current; fast = k != null && k.leftShiftKey.isPressed; if (k != null) { if (k.wKey.isPressed || k.upArrowKey.isPressed) z += 1; if (k.sKey.isPressed || k.downArrowKey.isPressed) z -= 1; if (k.dKey.isPressed || k.rightArrowKey.isPressed) x += 1; if (k.aKey.isPressed || k.leftArrowKey.isPressed) x -= 1; if (k.eKey.isPressed) y += 1; if (k.qKey.isPressed) y -= 1; } #else fast = Input.GetKey(KeyCode.LeftShift); if (Input.GetKey(KeyCode.W) || Input.GetKey(KeyCode.UpArrow)) z += 1; if (Input.GetKey(KeyCode.S) || Input.GetKey(KeyCode.DownArrow)) z -= 1; if (Input.GetKey(KeyCode.D) || Input.GetKey(KeyCode.RightArrow)) x += 1; if (Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.LeftArrow)) x -= 1; if (Input.GetKey(KeyCode.E)) y += 1; if (Input.GetKey(KeyCode.Q)) y -= 1; #endif return new Vector3(x, y, z); } void Update() { ReadMouse(out bool dragging, out Vector2 delta, out float scroll); if (TabPressed()) { roomMode = !roomMode; if (roomMode) { var e = transform.rotation.eulerAngles; roomYaw = e.y; roomPitch = e.x > 180f ? e.x - 360f : e.x; returning = false; } else returning = true; } if (roomMode) { if (dragging) { roomYaw += delta.x * roomLookSensitivity; roomPitch = Mathf.Clamp(roomPitch - delta.y * roomLookSensitivity, -85f, 85f); } var move = ReadMove(out bool fast); var rot = Quaternion.Euler(roomPitch, roomYaw, 0f); float speed = roomMoveSpeed * (fast ? 3f : 1f); var step = rot * new Vector3(move.x, 0f, move.z) + Vector3.up * move.y; transform.position += step * speed * Time.deltaTime + rot * Vector3.forward * scroll * speed * 0.15f; transform.rotation = Quaternion.Slerp(transform.rotation, rot, 1f - Mathf.Exp(-20f * Time.deltaTime)); return; } if (dragging) { targetYaw -= delta.x * dragSensitivity * 10f; targetPitch += delta.y * dragSensitivity * 10f; } targetDistance -= scroll * zoomSensitivity; targetYaw = Mathf.Clamp(targetYaw, -yawLimit, yawLimit); targetPitch = Mathf.Clamp(targetPitch, pitchRange.x, pitchRange.y); targetDistance = Mathf.Clamp(targetDistance, distanceRange.x, distanceRange.y); float k = 1f - Mathf.Exp(-smoothing * Time.deltaTime); yaw = Mathf.Lerp(yaw, targetYaw, k); pitch = Mathf.Lerp(pitch, targetPitch, k); distance = Mathf.Lerp(distance, targetDistance, k); Apply(); } void Apply() { var rot = Quaternion.Euler(pitch, yaw, 0f); var pos = pivot + rot * new Vector3(0f, 0f, -distance); if (returning) { // Glide back from wherever room mode left the camera float k = 1f - Mathf.Exp(-4f * Time.deltaTime); transform.position = Vector3.Lerp(transform.position, pos, k); transform.rotation = Quaternion.Slerp(transform.rotation, rot, k); if ((transform.position - pos).sqrMagnitude < 0.01f) returning = false; return; } transform.position = pos; transform.rotation = rot; } void OnGUI() { var style = new GUIStyle(GUI.skin.label) { fontSize = 14 }; style.normal.textColor = new Color(1f, 1f, 1f, 0.75f); GUI.Label(new Rect(12, 8, 700, 24), roomMode ? "Room view: WASD/arrows move, Q/E down/up, drag to look, Shift faster. Tab to return to the tank." : "Tank view: drag to orbit, scroll to zoom. Tab to look around the room.", style); } }