I'm having trouble adding zoom in/out functionality to the third-person view.

Godot Version

4.6.1.stable

Question

I’m new to using Godot on mobile, and I’m trying to add zoom in/out functionality to my third-person camera on a phone.

The zoom technically works, but InputEventMagnifyGesture and InputEventScreenDrag seem to overlap, causing the camera to jerk.

func _input(event):

if event is InputEventMagnifyGesture:

	spring_arm.spring_length \*= (1.0 / event.factor)

	spring_arm.spring_length = clamp(spring_arm.spring_length, min_zoom, max_zoom)

if event is InputEventScreenDrag:

	yaw_pivot.rotation.x -= event.relative.y \* sensitivity

	yaw_pivot.rotation.x = clamp(yaw_pivot.rotation.x, deg_to_rad(-90), deg_to_rad(90))

	pivot.rotation.y -= event.relative.x * sensitivity

I would like to know:

How do developers usually combine pinch zoom and drag rotation without conflicts?

Is there a more robust or efficient approach than relying on these two built-in event?

I found useful the camera3D property size which allows me to zoom without deformation. Moving the camera will change projection.

1 Like

Thank you, I’ll try that way!Thank you, I’ll try this method!

1 Like

These are for a Camera2D but this is how I do it:

Panning

func _input(event: InputEvent) -> void:
	if event is InputEventScreenDrag:
		_touch_points[event.index] = event.position
		if _touch_points.size() == 1:
			var new_position = -event.relative * touch_pan_speed
			camera.position = (camera.position + new_position).clamp(_camera_boundaries.position, _camera_boundaries.end)

Pinch Zoom

## The amount the player can zoom in. 1.0 means they cannot zoom in, and
## anything higher allows zooming in.
@export_range(1.0, 5.0, 0.01) var zoom_in_max := 1.0
## The amount the player can zoom out. 1.0 means they cannot zoom out, and
## anything lower allows zooming out.
@export_range(0.001, 1.0, 0.01) var zoom_out_max := 0.5

var _touches := {}
var _start_distance := 0.0


func _input(event: InputEvent) -> void:
	if not Engine.is_editor_hint():
		if event is InputEventScreenTouch:
			if event.pressed:
				_touches[event.index] = event.position
			else:
				_touches.erase(event.index)
		elif event is InputEventScreenDrag:
			_touches[event.index] = event.position
	
		_finger_count_check()


func _finger_count_check() -> void:
	if _touches.size() == 2:
		var fingers = _touches.values()
		_pinch_zoom(fingers[0].distance_to(fingers[1]))
	else:
		_start_distance = 0.0


func _pinch_zoom(current_distance: float) -> void:
	if _start_distance == 0.0:
		_start_distance = current_distance
	else:
		var zoom_factor: float = current_distance / _start_distance
		camera.zoom = clamp(camera.zoom * zoom_factor, Vector2.ONE * zoom_in_max, Vector2.ONE * zoom_out_max)

Full code in my Camera2D Plugin. I haven’t gotten time to put it into my Camera3D Plugin yet. There I just have a switch camera button to switch between the camera options I want to have available.

I’ve never tried using InputEventMagnifyGesture.

1 Like

Thank you!

1 Like