Rotating camera around player, but it jumps around?

4.3

Basicly it is a floating TPV camera that looks at & moving towards the player, it works fine, and you can rotate the camera around the player, and up & down, works fine too.
But the problem is: if you rotates the camera around and up/down together the camera moves backwards and jumps.

##The camera movement, works fine

func _process(delta: float) -> void:
	var t = $tpvcam.global_transform.origin
	var c = character.global_transform.origin

	var y = cam.pos.y*cam.range_pos #camera height & range
	var p = Vector3(c.x,c.y+y,c.z)
	var ndir = p.direction_to(t)
	var npos = p+(ndir*(cam.range*0.25))
	var cpy = (c.y+y) - t.y
	
	$tpvcam.global_transform.origin += (npos-t)*(delta*5)

	if abs(cpy) > 0: #camera height adjustment
		$tpvcam.global_transform.origin.y += cpy*delta*2
		
	$tpvcam.look_at(c)

THe camera rotating around player, works fine if you rotate horizontal or vertical, but with both the camera moves backwards and jumps around.

func _input(event):
	if event is InputEventMouseMotion

		var relx = event.relative.x
		var rely = event.relative.y
		
		var t = $tpvcam.global_transform.origin
		var c = character.global_transform.origin
		var d = c.distance_to(t)
## i guess the main problem occurs from here
		var rot = Vector2(t.x-c.x,t.z-c.z).angle() + relx*0.001
		$tpvcam.global_transform.origin = c + Vector3(cos(rot) * d, t.y-c.y, sin(rot) * d)

		$tpvcam.look_at(c)

##camera height
		if rely < 0 and cam.pos.y > cam.range_pos*0.01:
			cam.pos.y -= 0.01
		elif rely > 0 and cam.pos.y < cam.range_pos*0.04:
			cam.pos.y += 0.01

Anyone, any idea?

The main problem is that you’re handling horizontal and vertical rotations separately, which causes issues when combined

Maybe this pushes you in the right direction:


extends Node3D

@onready var tpvcam: Camera3D = $tpvcam
@onready var character: Node3D = $character  # Reference to your player character

# Camera settings
var cam = {
    range = 10.0,  # Distance from player
    range_pos = 5.0,  # Vertical range
    rot_speed = 0.001,  # Rotation sensitivity
    smooth_speed = 5.0,  # Camera movement smoothing
    height_speed = 2.0,  # Vertical movement speed
    min_pitch = -0.8,  # Minimum vertical angle (in radians)
    max_pitch = 0.8,   # Maximum vertical angle (in radians)
}

# Camera rotation state
var spherical = {
    distance = 10.0,  # Current distance from target
    theta = 0.0,      # Horizontal angle (in radians)
    phi = 0.0,        # Vertical angle (in radians)
}

func _ready() -> void:
    # Initialize camera position
    spherical.distance = cam.range * 0.25
    update_camera_position()

func _process(delta: float) -> void:
    var target_pos = get_target_position()
    var current_pos = tpvcam.global_transform.origin
    
    # Smoothly move camera towards target position
    tpvcam.global_transform.origin += (target_pos - current_pos) * (delta * cam.smooth_speed)
    
    # Always look at character
    tpvcam.look_at(character.global_transform.origin)

func _input(event: InputEvent) -> void:
    if event is InputEventMouseMotion:
        rotate_camera(event.relative)

func rotate_camera(relative: Vector2) -> void:
    # Update horizontal rotation (theta)
    spherical.theta -= relative.x * cam.rot_speed
    
    # Update vertical rotation (phi)
    spherical.phi -= relative.y * cam.rot_speed
    spherical.phi = clamp(spherical.phi, cam.min_pitch, cam.max_pitch)
    
    update_camera_position()

func get_target_position() -> Vector3:
    var char_pos = character.global_transform.origin
    var height_offset = Vector3(0, cam.range_pos * (0.01 + spherical.phi * 0.03), 0)
    return char_pos + height_offset

func update_camera_position() -> void:
    var target_pos = get_target_position()
    
    # Convert spherical coordinates to Cartesian
    var x = spherical.distance * cos(spherical.phi) * cos(spherical.theta)
    var y = spherical.distance * sin(spherical.phi)
    var z = spherical.distance * cos(spherical.phi) * sin(spherical.theta)
    
    tpvcam.global_transform.origin = target_pos + Vector3(x, y, z)
    tpvcam.look_at(target_pos)
1 Like

when you shows it, the problem are when the height are calculated with the distance, because the height increases the distance to the player.
So i replaced

var d = c.distance_to(t)

with

var d = Vector2(c.x,c.z).distance_to(Vector2(t.x,t.z))

thanks for your time!

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.