How to have a camera zoom in and out in 3D space

Godot Version

4.4.1

Question

Hi, i’m trying to learn how to have a CharacterBody3D to move around for my camera. Perhaps using CharacterBody3D isn’t very efficient to move a camera around using WASD but that’s what works for now. What I want to do now is to zoom in and out the camera and after thinking about it it makes sense for it to just be transformed by increasing the z and y coordinates so in theory i just need to set the velocity.y and velocity.x to the direction of the mouse wheel scroll (because im using the mouse wheel to zoom in) right?

and so after finding out that Input.get_vector isn’t the way bc its 4 directions instead of two and i only care about two direction, using get_axis is the way. and so then i use the transform.basis and multiply it by the get_axis thingy and so forth but I have an error that says that says

Valure of type “Vector3” cannot be assigned to a variable of type “float”

this is by the way the code that i have so far so it might be like a syntax error but yeah. SPEED is a constant that is a float. i use this same constant for the basic WASD movement and i have no issues with that so i doubt SPEED is the problem
var mouse_input := Input.get_axis("scrollDown","scrollUp") var mouse_dir := transform.basis * mouse_input if mouse_dir: velocity.y = mouse_dir.x * SPEED velocity.z = mouse_dir.y * SPEED else: velocity.y = move_toward(velocity.y, 0, SPEED) velocity.z = move_toward(velocity.z, 0, SPEED)
if this gets resolved I’ll make a youtube tutorial because the only zoom in and out stuff is for 2D for some reason when zooming in and out. also give me suggestions and links to other threads if how im doing the WASD movement using the CharacterBody3D is bad (i mean it wouldn’t be that bad if i use the collision features to limit the zoom in-game)

There’s two ways you can zoom. Here’s an example using field of view:

extends Camera3D

func _process(delta):
	var mouse_input = 0.0
	
	if(Input.is_action_just_pressed("scrollUp")):
		mouse_input += 1.0
	if(Input.is_action_just_pressed("scrollDown")):
		mouse_input -= 1.0
		
	fov -= mouse_input

That’s easier but if you want the camera to move, here’s an example for that:

extends Camera3D

func _process(delta):
	var mouse_input = 0.0
	if(Input.is_action_just_pressed("scrollUp")):
		mouse_input += 1.0
	if(Input.is_action_just_pressed("scrollDown")):
		mouse_input -= 1.0
	
	var mouse_dir = global_transform.basis.z * mouse_input
	global_position -= mouse_dir

You were using transform.basis, but you should use global_transform.basis.z. And get_axis wasn’t working for me for some reason (maybe it’s wrong type of action, I don’t know), so that’s why I used is_action_just_pressed.

You were also adjusting velocity. My test was just a Camera3D, not a CharacterBody, so I adjust the global_position directly.

If you’re making a tutorial, you might be interested in this:

extends Camera3D

func _process(delta):
	var mouse_input = 0.0
	if(Input.is_action_just_pressed("scrollUp")):
		mouse_input += 1.0
	if(Input.is_action_just_pressed("scrollDown")):
		mouse_input -= 1.0
	
	var mouse_dir = project_ray_normal(get_viewport().get_mouse_position())
	global_position += mouse_dir * mouse_input

This one zooms into where the mouse is pointing. Like in some drawing programs, or Godot editor in 2D mode. I think it’s a cool trick :slight_smile:

does the global_transform.basis and global_position also allow for moving the camera in all three axes? if so i could then just make the camera have the WASD motion as well. also is there such thing as global_rotation? like getting the tutorial for 3D rotation isn’t that bad this is just a clarifying question before i say that your response is the solution

Edit: i tested the code but now it looks like in global_position i just need to also adjust the y axis too. so do i do something like this?

var mouse_dir = (global_transform.basis.z + global_transform.basis.y) * mouse_input
global_position -= mouse_dir

Yes, but local allows this too. Local just wouldn’t play nice with velocity of CharacterBody3D, because the physics is in global space. Mixing local and global together would do weird things as soon as you rotate the camera.

Yes there is. Rotation is actually part of the basis under the hood. And basis is part of the transform and you have both local and global transforms. You even have global_scale too.

Now you lost me :upside_down_face:

(global_transform.basis.z + global_transform.basis.y) ← would give you a direction that’s up+back, and I don’t see how you would need that for zooming. Unless you want the camera to go higher when zooming out / down when zooming in?
If yes, that’s the way to do it.
If not, then maybe your camera is rotated on x-axis?

yes. basically its not actually zooming in and out: its backs away and goes higher at the same time, transforming both the z axis and the y axis equally, because the end result would be an angled top down camera view kinda like in League of Legends where it’s top down but at an angle (like 37-45 degree angle)

You should get the correct zoom behavior with just the z. If camera is looking down, the basis.z should point equally down (or up actually, because negative z is forward). Straight backwards from the camera’s point of view. If that makes sense.

Here’s what my test looks like:


This is using the code from my second example. Not adding .y separately.

If you get different results, then maybe something else is interfering.

wtf okay then lmao thank you :sob: i didn’t think the z direction would be based on the camera’s rotation :sob: :sob: :sob: