void Update() { if (Input.GetMouseButton(1)) { // If the mouse is pointing to UI do nothing. if (!EventSystem.current.IsPointerOverGameObject()) { if (_dragState == CameraDragState.Idle) { _dragState = CameraDragState.Begin; _dragAction = CameraDragAction.Tilt; } } } else { if (_dragAction == CameraDragAction.Tilt) { if (_dragState == CameraDragState.Move) { _dragState = CameraDragState.End; } } } if (Input.GetMouseButton(2)) { // If the mouse is pointing to UI do nothing. if (!EventSystem.current.IsPointerOverGameObject()) { if (_dragState == CameraDragState.Idle) { _dragState = CameraDragState.Begin; _dragAction = CameraDragAction.Pan; } } } else { if (_dragAction == CameraDragAction.Pan) { if (_dragState == CameraDragState.Move) { _dragState = CameraDragState.End; } } } // Process wheel input and camera zoom. if (_dragState == CameraDragState.Idle) { float wheelDelta = Input.mouseScrollDelta.y; if (wheelDelta > 0 || wheelDelta < 0) { // Zoom is done in the direction of the mouse. Ray pickRay = _camera.ScreenPointToRay(Input.mousePosition); var target = ProjectRayToGround(pickRay); var moveVector = (target - _camera.transform.position); if ((moveVector.magnitude > 5 && wheelDelta > 0) || (moveVector.magnitude < 60 && wheelDelta < 0)) { _camera.transform.position += moveVector.normalized * wheelDelta * 2.0f; } } } // Update Camera Panning and Tilt handle if (_dragState == CameraDragState.Begin) { // Update screen positions _screenDragStartPosition = Input.mousePosition; _screenDragCurrentPosition = Input.mousePosition; _cameraDragStartPosition = transform.position; if (_dragAction == CameraDragAction.Pan) { Ray pickRay = _camera.ScreenPointToRay(_screenDragStartPosition); _worldDragStartPosition = ProjectRayToGround(pickRay); _worldDragStartFarPosition = ProjectRayToCameraFarPlane(pickRay); } else if (_dragAction == CameraDragAction.Tilt) { _worldDragStartPosition = ProjectRayToGround(new Ray(_camera.transform.position, _camera.transform.forward)); _cameraDragCurrentViewportPosition = _camera.ScreenToViewportPoint(_screenDragStartPosition); } _dragState = CameraDragState.Move; } if (_dragState == CameraDragState.Move) { _screenDragCurrentPosition = Input.mousePosition; if (_dragAction == CameraDragAction.Pan) { // This panning algorithm some people call it perfect panning as it maintains the cursor in the original position while panning. Ray pickRay = _camera.ScreenPointToRay(_screenDragCurrentPosition); var worldDragCurrentFarPosition = ProjectRayToCameraFarPlane(pickRay); float moveDistance = (_cameraDragStartPosition - _worldDragStartPosition).magnitude * (_worldDragStartFarPosition - worldDragCurrentFarPosition).magnitude / (_worldDragStartFarPosition - _worldDragStartPosition).magnitude; var dir = (_worldDragStartFarPosition - worldDragCurrentFarPosition).normalized; _camera.transform.position = _cameraDragStartPosition + dir * moveDistance; } else if (_dragAction == CameraDragAction.Tilt) { // This is a camera center targeted Orbital Rotation. var lastViewportPosition = _cameraDragCurrentViewportPosition; _cameraDragCurrentViewportPosition = _camera.ScreenToViewportPoint(_screenDragCurrentPosition); var deltaViewportMovement = _cameraDragCurrentViewportPosition - lastViewportPosition; _camera.transform.RotateAround(_worldDragStartPosition, Vector3.up, deltaViewportMovement.x * 60); _camera.transform.RotateAround(_worldDragStartPosition, _camera.transform.right, -deltaViewportMovement.y * 60); } } if (_dragState == CameraDragState.End) { _screenDragCurrentPosition = Input.mousePosition; _dragState = CameraDragState.Idle; _dragAction = CameraDragAction.None; } // Dont allow the camera go too far away // This will create a sphere with center on [0,0,0] of size 80. If the camera move // far from that clamp that value if (_camera.transform.position.magnitude > 80) { _camera.transform.position = Vector3.ClampMagnitude(_camera.transform.position, 80); } }
private void OnEnable() { _dragAction = CameraDragAction.None; _dragState = CameraDragState.Idle; }