#if UNITY_EDITOR using System.Collections.Generic; using UnityEngine; namespace Mountools.Tools { public class ToolFreeCamera : MonoBehaviour { [HideInInspector] public string cameraRotationX = "Mouse Y"; [HideInInspector] public string cameraRotationY = "Mouse X"; [HideInInspector] public string cameraRotationZ = "Horizontal"; [HideInInspector] public string cameraForwardAxisName = "Vertical"; [HideInInspector] public string cameraFastMoveButton = "Fire3"; [HideInInspector] public string enableRotationZ = "Fire1"; [HideInInspector] public string cameraRotationZRecover = "Jump"; public float cameraSensitivity = 150f; public float cameraMovingSpeed = 20f; public float cameraFastMovingSpeed = 50f; public bool canCameraRotationZ; // 场景内相机状态 private readonly Dictionary _cameraStatus = new(); private float _currentSpeed; private Vector3 _currentRotation; // 相机状态 public bool active => FindObjectOfType() != null; public static void FreeCameraEnter() { if (! Application.isPlaying) return; if (FindObjectOfType() != null) return; GameObject gameObject = new GameObject("Free Camera"); Camera selfCamera = gameObject.AddComponent(); ToolFreeCamera freeCamera = gameObject.AddComponent(); Camera[] cameras = FindObjectsOfType(true); freeCamera._cameraStatus.Clear(); foreach (var cam in cameras) { if (cam == selfCamera) continue; freeCamera._cameraStatus.Add(cam, cam.gameObject.activeSelf); if (cam.gameObject.activeSelf) { var camTransform = cam.transform; var selfCameraTransform = selfCamera.transform; selfCameraTransform.position = camTransform.position; freeCamera._currentRotation = camTransform.rotation.eulerAngles; selfCamera.fieldOfView = cam.fieldOfView; selfCamera.orthographic = cam.orthographic; selfCamera.depth = cam.depth; selfCamera.aspect = cam.aspect; selfCamera.clearFlags = cam.clearFlags; selfCamera.backgroundColor = cam.backgroundColor; cam.gameObject.SetActive(false); continue; } cam.gameObject.SetActive(false); } Cursor.lockState = CursorLockMode.Locked; Cursor.visible = false; } public static void FreeCameraExit() { if (! Application.isPlaying) return; var freeCamera = FindObjectOfType(); if (freeCamera == null) return; freeCamera.gameObject.SetActive(false); foreach (var cameras in freeCamera._cameraStatus) { cameras.Key.gameObject.SetActive(cameras.Value); } Destroy(freeCamera.gameObject); } private void Update() { if (Input.GetKeyDown(KeyCode.Mouse0)) { Cursor.lockState = CursorLockMode.Locked; Cursor.visible = false; } if (Input.GetKeyDown(KeyCode.Mouse1) || Input.GetKeyDown(KeyCode.Escape)) { if (Cursor.lockState == CursorLockMode.None) { FreeCameraExit(); } else { Cursor.lockState = CursorLockMode.None; Cursor.visible = true; } } UpdateCameraRotation(); } public void UpdateCameraRotation() { if (Cursor.lockState == CursorLockMode.None) return; var camRotationZ = Input.GetAxis(cameraRotationZ); var canRotationZ = canCameraRotationZ && Input.GetButton(enableRotationZ); // Rotation Control var rotationVector = new Vector3 { x = Input.GetAxis(cameraRotationX), y = Input.GetAxis(cameraRotationY), z = canRotationZ ? camRotationZ : 0 }; // Change Rotation var t = transform; _currentRotation.x -= cameraSensitivity * Time.fixedDeltaTime * rotationVector.x; _currentRotation.y += cameraSensitivity * Time.fixedDeltaTime * rotationVector.y; _currentRotation.z -= cameraSensitivity * Time.fixedDeltaTime * rotationVector.z; _currentRotation.x = ClampRotation(_currentRotation.x, -90, 90); _currentRotation.z = ClampRotation(_currentRotation.z, -90, 90); if (Input.GetButton(cameraRotationZRecover)) _currentRotation.z = Mathf.Lerp(_currentRotation.z, 0, 0.2f); t.rotation = Quaternion.Euler(_currentRotation); // Movement Control var movementAxisForward = Input.GetAxis(cameraForwardAxisName); var movementAxisRight = canRotationZ ? 0 : camRotationZ; var speed = Input.GetButton(cameraFastMoveButton) ? cameraFastMovingSpeed : cameraMovingSpeed; _currentSpeed = Mathf.Lerp(_currentSpeed, speed, 0.3f); t.position += t.forward * (Time.deltaTime * _currentSpeed * movementAxisForward) + t.right * (Time.deltaTime * _currentSpeed * movementAxisRight); } private static float ClampRotation(float n, float min, float max) { if (n < -360) n += 360; if (n > 360) n-= 360; return Mathf.Clamp(n, min, max); } } } #endif