Is it ok to lerp the camera to my player for First Person?

Godot Version

4.3

Question

I have a 144hz monitor and I’ve been having jittering issues when moving around in my first person game. I heard online that moving the camera separate from the player physics was the solution so I tried that by coding my camera to follow my player’s global position camera.position = player.global_position. But the jittering issue persisted. I then decided to use lerp to move the camera camera.position = camera.position.lerp(head.global_position, delta*30) and that kind of seems to fix the jittering issue, but I don’t know if that’s the correct solution, it definitely feels smoother but I feel like it could be even more smoother lol. Thanks for reading.

I think what you’re doing is that you have your camera movement code in _physics_process() use _process() instead _physics_process() runs 60 times per second by default

also Try the RemoteTransform node

2 Likes

I do have my camera movement in _process(), but I’ll take a look at that RemoteTransform node. Thanks!

Is your position smoothing enabled in your camera (I think it is on by default but not sure). It makes a big difference.

I used to lerp my camera directly but now I treat my camera like a player or enemy node. It has a speed, an acceleration, a state manager for different behaviours and motions etc. It took ages to get it right. I also use a PlayerManager autoload singleton to share the players position, not only with the camera but with my enemy nodes as well.

PS I still use lerps for any camera motion, but I lerp everything :slight_smile:

1 Like

You can use lerp properly with Engine.get_physics_interpolation_fraction(), this will only leave your camera one frame behind

Engine.get_physics_interpolation_fraction() returns 0.0 to 1.0 the progress between physics frames. i.e. at 120hz refresh rate, and 60 physics tick this will usually be 0.0 (on physics tick) or 0.5 (refreshed between a physics tick)

lerp takes two values and returns a mid-point based on the final “weight” parameter, where 0.0 is the first argument, 1.0 is the second argument, and anything in-between is calculated.

@export var player: Node3D
var player_last_position: Vector3


func _process(_delta: float) -> void:
    var new_position = player_last_position.lerp(player.global_position, Engine.get_physics_interpolation_fraction())
    camera.position = new_position


# trying to capture the player's position after a physics update,
# might be best to have the player send this information upwards
# with a signal after move_and_slide() for instance
func _physics_process(_delta: float) -> void:
    player_last_position = player.global_position

Your code should’ve ended up with a pretty smooth camera, make sure the jitter doesn’t come from frame lag, use the profilier or in the 3D view click “Perspective > View frame time”

1 Like

Another possibility would be to reparent the camera to your character.

This would not work as Godot does not have 3D physics interpolation bulit-in, and the player being a physics object only updates position at the physics tick rate.

1 Like

I can’t notice the difference between using Engine.get_physics_interpolation_fraction() or using what I currently have delta * 30, don’t know if my eyes are just deceiving me, but any FP game just feels so smooth looking around at 144 fps compared to what I have. I might try doing something similar in unity just to compare.