Menu UI + camera settings problem

Godot Version

4.6

Question

Hello! Im making a “horse maker” project for fun, and I encountered a problem that has me stumped. I wanted a menu like in spore creature creator that slides in and out, and its mostly good except the zooming doesnt feel quite right when the menu is open

Sadly cant put attachments but basically I use an orthogonal camera that slides to the right when you open the menu, I didnt like the look of perspective camera and I attached mouse wheel to the camera size so I can zoom in and out, obviously because the model is not in the middle of the screen it zooms in its hind which just feels wonky from a players perspective I think. I tried moving the camera with zoom (in z) but it didnt work well, the movement and zoom were obviously unsynched and couldnt get it to work right. Tried changing to perspective, didnt like how it looked. Tried “look at” but it just kind of changed the camera rotation so it looked from above the horse and the zoom worked the same way, which was to be expected.

At this point I dont know if what Im asking is actually impossible and have to give it up, I searched through spore footage and no lightbulbs were lit.

So if someone knows how to replicate the look of the model going to the side to make way for the menu while keeping zoom focused on it itd be great. If you think its impossible, please tell me im losing my mind lol

func _ready() -> void:
    print("hello world")

You can upload the video to streamable.com and post a link here. This will make it much easier to understand the issue.

Also, please make sure to paste your current script here.

2 Likes

Sure, heres my video showcasing the “problem” and my code (albeit its a bit embarassing to share since im so new at this haha):
extends Node
@export var pivot_node: Node3D
@export var target: Node3D
@export var camera: Camera3D
@export var sensitivity := 0.01

@export var zoom_speed := 0.5
@export var min_zoom:= 1.0
@export var max_zoom:= 5.0
@export var max_zoom_offset := .01

@export var pan_speed := 0.001
@export var max_pan := .5

var pivot = 0.0
var zoom := 4.
var zoom_offset := .001
var rotating := false
var panning := false

var camera_default_zoom: float
var pivot_default_rotation: Vector3
var camera_default_position: Vector3
var camera_default_menu_closed: Vector3
var camera_default_menu_opened: Vector3

var is_menu_open := false

func _ready() → void:

pivot_default_rotation = pivot_node.rotation
camera_default_zoom = camera.size

camera_default_menu_closed = camera.position 

camera_default_menu_opened = camera.position 
camera_default_menu_opened.z = -.85

func _input(event: InputEvent) → void:
if event is InputEventMouseButton:
match event.button_index:
MOUSE_BUTTON_RIGHT:
rotating = event.pressed
MOUSE_BUTTON_WHEEL_DOWN:
if get_viewport().gui_get_hovered_control() != null:
return
zoom_camera(zoom_speed)
MOUSE_BUTTON_WHEEL_UP:
if get_viewport().gui_get_hovered_control() != null:
return
zoom_camera(-zoom_speed)
MOUSE_BUTTON_MIDDLE:
panning = event.pressed
elif event is InputEventMouseMotion:
if rotating:
rotate_target(event.relative)
if panning:
pan_camera(event.relative)

elif event is InputEvent:
	if event.is_action_pressed("r"):
		reset_camera()

func rotate_target(relative: Vector2):
if pivot_node == null:
return

#Horizontal
pivot_node.rotate_y(-relative.x * sensitivity)
#Vertical
pivot += relative.y * sensitivity*0.1
pivot = clamp(pivot, deg_to_rad(-10), deg_to_rad(10))
pivot_node.rotation.z = pivot

func zoom_camera(amount: float):
if camera == null:
print(“No camera assigned!”)
return

zoom += amount
zoom = clamp(zoom, min_zoom, max_zoom)

camera.size = zoom

func pan_camera(relative: Vector2):
if camera == null:
return
set_camera_default_position()

var pan_limit = max_pan * zoom

var offset = camera.position - camera_default_position 
offset.y -= relative.y * pan_speed * zoom
offset.y = clamp(offset.y, -pan_limit, pan_limit+.5*zoom)
offset.z -= relative.x * pan_speed * zoom
offset.z = clamp(offset.z, -pan_limit, pan_limit+1.*zoom)

camera.position = camera_default_position + offset

func reset_camera():
set_camera_default_position()

camera.position = camera_default_position
pivot_node.rotation = pivot_default_rotation
camera.size = camera_default_zoom

func open_menu():
is_menu_open = true
var slide_out_anim = create_tween()
slide_out_anim.tween_property(camera, “position:z”, -.85 , 0.4)

func close_menu():
is_menu_open = false
var slide_in_anim = create_tween()
slide_in_anim.tween_property(camera, “position:z”, 0, 0.4)

func set_camera_default_position():
if is_menu_open:
camera_default_position = camera_default_menu_opened
else:
camera_default_position = camera_default_menu_closed

func _on_ui_menu_opened() → void:
open_menu()

func _on_ui_menu_closed() → void:
close_menu()

Your code is not formatted properly, it’s very hard to read in this format. You should put your code between tripple backticks ``` on both sides.

```gdscript
<your code here>
```

Thanks but I actually found a solution, instead of moving the camera Im using a subviewport with a viewport container with clip contents and I move that, thank you anyway!!!