using UnityEngine; public class ModelViewerOrbitCamera : MonoBehaviour { [Header("观察目标")] [SerializeField] private Transform target; // 要观察的模型 [Header("旋转设置")] [SerializeField] private float rotationSpeed = 5.0f; [SerializeField] private float autoRotationSpeed = 0.5f; [SerializeField] private float rotationSmoothness = 5.0f; [Header("缩放设置")] [SerializeField] private float zoomSpeed = 5.0f; [SerializeField] private float minZoomDistance = 1.0f; [SerializeField] private float maxZoomDistance = 20.0f; [SerializeField] private float defaultZoomDistance = 5.0f; [Header("平移设置")] [SerializeField] private float panSpeed = 0.5f; [Header("自动旋转")] [SerializeField] private bool enableAutoRotation = false; [Header("鼠标控制")] [SerializeField] private MouseButton rotateButton = MouseButton.Left; [SerializeField] private MouseButton panButton = MouseButton.Middle; [SerializeField] private float mouseSensitivity = 1.0f; [Header("触摸屏控制")] [SerializeField] private float touchSensitivity = 0.5f; [Header("边界限制")] [SerializeField] private Vector2 verticalAngleLimit = new Vector2(10f, 80f); private Vector3 currentRotation = Vector3.zero; private Vector3 targetRotation = Vector3.zero; private float currentDistance = 5.0f; private float targetDistance = 5.0f; private Vector3 targetPositionOffset = Vector3.zero; private Vector3 currentTargetPositionOffset = Vector3.zero; private Vector3 lastMousePosition = Vector3.zero; private Vector3 lastPanPosition = Vector3.zero; private enum MouseButton { Left = 0, Right = 1, Middle = 2 } void Start() { // 如果未指定目标,尝试查找 if (target == null) { // 可以在这里添加自动查找模型的逻辑 // 例如:target = GameObject.Find("Model").transform; } // 初始化距离 currentDistance = defaultZoomDistance; targetDistance = defaultZoomDistance; // 初始化旋转 Vector3 angles = transform.eulerAngles; currentRotation = new Vector3(angles.y, angles.x, 0); targetRotation = currentRotation; // 计算初始位置 UpdateCameraPosition(); } void LateUpdate() { if (target == null) return; HandleInput(); UpdateCameraPosition(); } private void HandleInput() { // 处理桌面端输入 HandleDesktopInput(); // 处理移动端输入 HandleTouchInput(); } private void HandleDesktopInput() { // 旋转控制 if (Input.GetMouseButton((int)rotateButton)) { float horizontal = Input.GetAxis("Mouse X") * rotationSpeed * mouseSensitivity; float vertical = -Input.GetAxis("Mouse Y") * rotationSpeed * mouseSensitivity; targetRotation.x += horizontal; targetRotation.y += vertical; // 限制垂直角度 targetRotation.y = Mathf.Clamp(targetRotation.y, verticalAngleLimit.x, verticalAngleLimit.y); // 停止自动旋转 enableAutoRotation = false; } // 平移控制 if (Input.GetMouseButton((int)panButton)) { if (Input.GetMouseButtonDown((int)panButton)) { lastPanPosition = Input.mousePosition; } Vector3 delta = Input.mousePosition - lastPanPosition; // 计算平移方向(基于相机的右和上方向) Vector3 right = transform.right; Vector3 up = transform.up; right.y = 0; // 保持水平平移 up.y = 0; targetPositionOffset -= (right * delta.x + up * delta.y) * panSpeed * 0.01f; lastPanPosition = Input.mousePosition; } // 缩放控制 float scroll = Input.GetAxis("Mouse ScrollWheel"); if (Mathf.Abs(scroll) > 0.01f) { targetDistance -= scroll * zoomSpeed; targetDistance = Mathf.Clamp(targetDistance, minZoomDistance, maxZoomDistance); } // 重置按钮 if (Input.GetKeyDown(KeyCode.R)) { ResetView(); } // 自动旋转切换 if (Input.GetKeyDown(KeyCode.A)) { enableAutoRotation = !enableAutoRotation; } } private void HandleTouchInput() { #if UNITY_IOS || UNITY_ANDROID || UNITY_WEBGL if (Input.touchCount == 1) { Touch touch = Input.GetTouch(0); if (touch.phase == TouchPhase.Moved) { Vector2 delta = touch.deltaPosition; targetRotation.x += delta.x * rotationSpeed * touchSensitivity * 0.1f; targetRotation.y -= delta.y * rotationSpeed * touchSensitivity * 0.1f; // 限制垂直角度 targetRotation.y = Mathf.Clamp(targetRotation.y, verticalAngleLimit.x, verticalAngleLimit.y); } } else if (Input.touchCount == 2) { Touch touchZero = Input.GetTouch(0); Touch touchOne = Input.GetTouch(1); Vector2 touchZeroPrevPos = touchZero.position - touchZero.deltaPosition; Vector2 touchOnePrevPos = touchOne.position - touchOne.deltaPosition; float prevTouchDeltaMag = (touchZeroPrevPos - touchOnePrevPos).magnitude; float touchDeltaMag = (touchZero.position - touchOne.position).magnitude; float deltaMagnitudeDiff = prevTouchDeltaMag - touchDeltaMag; targetDistance += deltaMagnitudeDiff * zoomSpeed * 0.01f; targetDistance = Mathf.Clamp(targetDistance, minZoomDistance, maxZoomDistance); } #endif } private void UpdateCameraPosition() { // 自动旋转 if (enableAutoRotation) { targetRotation.x += autoRotationSpeed; } // 应用旋转平滑 currentRotation = Vector3.Lerp(currentRotation, targetRotation, rotationSmoothness * Time.deltaTime); // 应用距离平滑 currentDistance = Mathf.Lerp(currentDistance, targetDistance, rotationSmoothness * Time.deltaTime); // 应用平移平滑 currentTargetPositionOffset = Vector3.Lerp(currentTargetPositionOffset, targetPositionOffset, rotationSmoothness * Time.deltaTime); // 计算旋转 Quaternion rotation = Quaternion.Euler(currentRotation.y, currentRotation.x, 0); // 计算位置 Vector3 position = rotation * new Vector3(0, 0, -currentDistance) + target.position + currentTargetPositionOffset; // 应用变换 transform.position = position; transform.LookAt(target.position + currentTargetPositionOffset); // 可选:使相机稍微向上看 // transform.LookAt(target.position + currentTargetPositionOffset + Vector3.up * 0.5f); } // 公共方法 /// /// 重置视角 /// public void ResetView() { targetRotation = new Vector3(0, 45f, 0); // 默认视角 targetDistance = defaultZoomDistance; targetPositionOffset = Vector3.zero; enableAutoRotation = false; } /// /// 聚焦到模型 /// public void FocusOnModel() { if (target != null) { targetPositionOffset = Vector3.zero; } } /// /// 设置观察目标 /// public void SetTarget(Transform newTarget) { target = newTarget; ResetView(); } /// /// 设置观察目标 /// public void SetTarget(GameObject newTarget) { if (newTarget != null) { target = newTarget.transform; ResetView(); } } /// /// 设置观察目标的中心点 /// public void SetTargetOffset(Vector3 offset) { targetPositionOffset = offset; } /// /// 设置缩放距离 /// public void SetZoomDistance(float distance) { targetDistance = Mathf.Clamp(distance, minZoomDistance, maxZoomDistance); } /// /// 设置旋转角度 /// public void SetRotation(float horizontal, float vertical) { targetRotation = new Vector3(horizontal, Mathf.Clamp(vertical, verticalAngleLimit.x, verticalAngleLimit.y), 0); } /// /// 切换自动旋转 /// public void ToggleAutoRotation(bool enable) { enableAutoRotation = enable; } /// /// 设置自动旋转速度 /// public void SetAutoRotationSpeed(float speed) { autoRotationSpeed = speed; } // 编辑器调试信息 void OnGUI() { if (Application.isEditor) { GUI.Label(new Rect(10, 10, 300, 20), $"上帝视角观察器 - 模型查看器"); if (target != null) { GUI.Label(new Rect(10, 30, 300, 20), $"目标: {target.name}"); } else { GUI.Label(new Rect(10, 30, 300, 20), "目标: 未设置 (请在Inspector中指定)"); } GUI.Label(new Rect(10, 50, 300, 20), $"旋转: ({currentRotation.x:F1}, {currentRotation.y:F1})"); GUI.Label(new Rect(10, 70, 300, 20), $"距离: {currentDistance:F1}"); GUI.Label(new Rect(10, 90, 300, 20), $"自动旋转: {(enableAutoRotation ? "开" : "关")}"); GUI.Label(new Rect(10, 120, 400, 20), "控制说明:"); GUI.Label(new Rect(10, 140, 400, 20), "左键拖拽: 旋转视角"); GUI.Label(new Rect(10, 160, 400, 20), "中键拖拽: 平移视角"); GUI.Label(new Rect(10, 180, 400, 20), "滚轮: 缩放"); GUI.Label(new Rect(10, 200, 400, 20), "R键: 重置视角"); GUI.Label(new Rect(10, 220, 400, 20), "A键: 切换自动旋转"); } } // 在Scene视图中绘制辅助线 void OnDrawGizmosSelected() { if (target != null) { Gizmos.color = Color.yellow; Gizmos.DrawWireSphere(target.position + currentTargetPositionOffset, 0.5f); Gizmos.DrawLine(target.position + currentTargetPositionOffset, transform.position); } } }