Jitter on player followed by camera

Godot Version

4.6

Question

Why is there so much jitter visible on the player in this?

Here are some notes and what I’ve already tried:

  • physics interpolation is ON. the jitter goes away if it is off, but of course then the player and camera both move at a very visible 60hz, which doesn’t feel great.
  • changing physics jitter fix doesn’t do much.
  • both the player and camera target move in _physics_process, with the camera itself updating position by doing global_transform = camera.target.get_global_transform_interpolated() during it’s _process. I previously tried moving the camera target in _process but the result was largely the same, with neither removing jitter.
  • both the camera and camera target have Top level on, so they don’t move when the parent characterbody3d moves.
  • removing the lerped camera movement does not remove the jitter.

Scene structure

Scripts

CameraTarget

extends Marker3D

@export var OFFSET := Vector3(0, 1, 6)
@export var CAMERA_SPEED := 5
@export var LOOKAROUND_RADIUS := 2
@export var MAX_DISTANCE:= 1

@onready var player = $".."

func _physics_process(delta: float) -> void:
	var current_pos = global_position
	
	var lookaround = Input.get_vector(
		"look_left",
		"look_right",
		"look_down",
		"look_up"
		) * LOOKAROUND_RADIUS
	
	var offset = Vector3(
		OFFSET.x + lookaround.x,
		OFFSET.y + lookaround.y,
		OFFSET.z
	)
	
	var target = player.global_position + offset

	target = current_pos.lerp(target, delta * CAMERA_SPEED)
	
	global_position = target

Camera3D

extends Camera3D

@onready var camera_target: Marker3D = $"../CameraTarget"

func _process(_delta: float) -> void:
	global_transform = camera_target.get_global_transform_interpolated()

Player

extends CharacterBody3D

const MAX_SPEED := 5;
const ACCELERATION := 100;
const JUMP_VELOCITY := 4;

var current_x_velocity: float

func _physics_process(delta: float) -> void:
	var move_dir := Input.get_axis("move_left", "move_right");
	var desired_x_velocity = move_dir * MAX_SPEED;
	
	current_x_velocity = lerp(current_x_velocity, desired_x_velocity, ACCELERATION * delta)
	
	var jump_modifier = 1;
	
	# cut gravity in half if jump is held to allow higher jumps
	if not is_on_floor() && velocity.y > 0 && Input.is_action_pressed("move_jump"):
		jump_modifier = 0.5;
	
	if Input.is_action_pressed("move_jump") && is_on_floor():
		velocity.y = JUMP_VELOCITY;
	
	velocity = Vector3(current_x_velocity, velocity.y, 0);
	
	# apply gravity
	velocity += get_gravity() * delta * jump_modifier;
	
	move_and_slide();

If you are setting the Camera’s global position anyways you shouldn’t child it to the Player physics object. I would bet the interpolation system does a bad job with Top Level, most thing do not like Top Level nodes.

Gave it a go, no luck. Having the camera script run in process or physics process, and with or without the player position being fetched with get_global_transform_interpolated(), there is jitter in all combinations :frowning:

However, when lerping is disabled, a new strange issue occurs – the camera lags behind the player object at a small fixed distance when moving. Not sure if this is relevant but worth throwing in there just in case!

Did you try playing with Camera’s physics process priority ?