Pan, Zoom and Orbit Behavior (Unity)

z4gon
z4gon

UI elements to Orbit, Zoom, Pan and Reset View. GUIs to tweak values for demo purposes.

Source Code

See Project in GitHub 👩‍💻

References

Table of Content

Final Result

A demo scene with view control to navigate the scene, and a playground to tweak values in the demo.

Picture Picture

Input Actions

Using the Input System Package from Unity, create an Input Actions asset and setup the Action Maps.

  • Orbit and Pan will be Action Type set to Value, because we want the actual Vector2 coming from the analog stick on screen.
  • The Control Type will be set to Stick, so we can bind it to the Gamepad Stick.
  • The Binding will be set to the Left Stick and Right Stick, correspondingly.

Picture Picture

On Screen Controls

We will need to add Unity UI Game Objects to represent the analog sticks on the screen.

  • Adding the built in On-Screen Stick behavior to the image component will do it.
  • We need to set the Control Path of the on screen stick to Left Stick [Gamepad] and Right Stick [Gamepad] correspondingly.

Picture Picture Picture

Connecting to the CameraMovement

  • The CameraMovement classes will listen to events such as OnPan or OnPointerDelta.
  • And internally will use these inputs to move the camera accordingly.

Picture Picture

Input Signals

1private void OnPan(InputValue value) => panAmount = value.Get<Vector2>(); 2private void OnOrbit(InputValue value) => orbitAmount = value.Get<Vector2>();
1private void OnPointerDelta(InputValue value) 2{ 3 orbitAmount = isOrbiting ? value.Get<Vector2>() : Vector2.zero; 4 panAmount = isPanning ? value.Get<Vector2>() * -1.0f : Vector2.zero; 5} 6 7private void OnOrbitStart(InputValue value) 8{ 9 isOrbiting = value.isPressed; 10} 11 12private void OnPanStart(InputValue value) 13{ 14 isPanning = value.isPressed; 15} 16 17private void OnZoom(InputValue value) 18{ 19 zoomAmount = value.Get<float>(); 20}

Pan View

  • Given the Vector2 amount of movement from the analog stick, we move the camera along its up/down and right/left directions.
  • We also reposition the orbit pivot, which will be used later for orbiting around it.
1private void HandlePan() 2{ 3 if (panAmount == Vector2.zero) { return; } 4 5 var direction = camera.transform.right * panAmount.x + camera.transform.up * panAmount.y; 6 7 camera.transform.position += (direction * panSpeed * Time.deltaTime); 8 PositionPivot(); 9}
  • The Pivot point is calculated by raycasting the Camera forward direction into a Plane defined parallel to the ground, at the Zero position.
1private void PositionPivot() 2{ 3 var distance = 0.0f; 4 5 var ray = new Ray(cameraTransform.position, cameraTransform.forward); 6 7 if (floorPlane.Raycast(ray, out distance)) 8 { 9 transform.position = ray.GetPoint(distance); 10 } 11}

Zoom View

  • Zooming is easier, just moving the Camera along its forward direction.
1private void HandleZoom() 2{ 3 if (zoomAmount == 0.0f) { return; } 4 5 var direction = camera.transform.forward; 6 camera.transform.position += (direction * zoomAmount * Time.deltaTime); 7}

Orbit View

  • Orbiting is easy thanks to the RotateAround helper function from Unity.
  • We make the Camera rotate around the pivot position, around the world up direction, and around the right direction of the camera.
1private void HandleOrbit() 2{ 3 if (orbitAmount == Vector2.zero) { return; } 4 5 cameraTransform.RotateAround(transform.position, Vector3.up, -1.0f * orbitAmount.x * orbitSpeed * Time.deltaTime); 6 cameraTransform.RotateAround(transform.position, cameraTransform.right, orbitAmount.y * orbitSpeed * Time.deltaTime); 7}

GUIs for Playground

  • A set of GUI inputs to let you tweak values for the demo.
  • These can be hooked up via events to your objects and shaders, to showcase behavior.

Picture Picture