Godot Version
4.1.3.stable
Question
Hi there! I’m making a first-person horror game and was wondering how to make the turning of the camera delayed. The camera is controlled by mouse movement and I imagine that I’d have to set the new position to a target value, then reach that gradually, but I’m not sure how to do this. Here are my camera related functions in my player script so far.
func _ready():
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
func _input(event):
if Input.is_action_pressed("pause"):
pause_menu.show()
Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
if event is InputEventMouseMotion and pause_menu.visible == false:
var MouseEvent = event.relative * mouse_sens
CameraLook(MouseEvent)
func CameraLook(Movement: Vector2):
camera_rotation += Movement
camera_rotation.y = clamp(camera_rotation.y, -1.5, 1.2)
transform.basis = Basis()
camera_pivot.transform.basis = Basis()
rotate_object_local(Vector3(0, 1, 0), -camera_rotation.x)
camera_pivot.rotate_object_local(Vector3(1, 0, 0), -camera_rotation.y)
Any help is much appreciated. Thank you!
wchc
December 24, 2024, 1:00am
2
Have you tried tweening?
Or lerping?
Let me know if you have troubles implementing these in your project.
Hi, thank you for your response. I can’t say I’ve heard of either of these before. How would I go about implementing these to achieve this?
wchc
January 7, 2025, 12:25pm
4
See here my little demo
Here’s the scene structure
Here’s the code attached to the root Node.
extends Node3D
@export var camera_pivot: Node3D
@export var camera: Node3D
var rotation_speed: float = 0.005
var threshold_to_target: float = 0.01
var target_rotation: Vector2
var lerp_speed: float = 0.7
func _ready() -> void:
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
func _unhandled_input(event: InputEvent) -> void:
if event is InputEventMouseMotion:
var mouse_motion_event: InputEventMouseMotion = event as InputEventMouseMotion
target_rotation -= mouse_motion_event.relative * rotation_speed
target_rotation.y = clampf(target_rotation.y, PI/-2, PI/2)
func _process(delta: float) -> void:
var horizontal_difference: float = absf(camera_pivot.rotation.y - target_rotation.x)
if horizontal_difference > threshold_to_target:
camera_pivot.rotation.y = lerpf(camera_pivot.rotation.y, target_rotation.x, horizontal_difference * lerp_speed)
var vertical_difference: float = absf(camera.rotation.x - target_rotation.y)
if vertical_difference > threshold_to_target:
camera.rotation.x = lerpf(camera.rotation.x, target_rotation.y, vertical_difference * lerp_speed)
You need to adjust it to your project, but hopefully this can shed some light how you can use lerp for smoothed transitioning.
2 Likes
This is absolutely fantastic, thank you very much!
1 Like
I have noticed, this is brilliant, but does not work with Godot’s template movement, as the camera does not follow the movement. How can I fix this?
wchc
January 7, 2025, 7:41pm
7
I adjusted the code to be usable with movement as well and simplified it a bit enjoy
extends CharacterBody3D
@export var camera: Node3D
var movement_speed: float = 150.0
var rotation_speed: float = 0.005
var ease_curve: float = 0.1
var target_rotation: Vector2
func _ready() -> void:
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
func _unhandled_input(event: InputEvent) -> void:
if event is InputEventMouseMotion:
var mouse_motion_event: InputEventMouseMotion = event as InputEventMouseMotion
target_rotation -= mouse_motion_event.relative * rotation_speed
target_rotation.y = clampf(target_rotation.y, PI/-2, PI/2)
func _physics_process(delta: float) -> void:
rotation.y = lerp_angle(rotation.y, target_rotation.x, ease(delta, ease_curve))
camera.rotation.x = lerp_angle(camera.rotation.x, target_rotation.y, ease(delta, ease_curve))
var movement_direction: Vector3 = Vector3.ZERO
if Input.is_action_pressed("ui_up"):
movement_direction += Vector3.FORWARD
if Input.is_action_pressed("ui_down"):
movement_direction += Vector3.BACK
if Input.is_action_pressed("ui_right"):
movement_direction += Vector3.RIGHT
if Input.is_action_pressed("ui_left"):
movement_direction += Vector3.LEFT
velocity = basis * movement_direction * delta * movement_speed
move_and_slide()
Have you tried the InterpolatedCamera plugin? InterpolatedCamera3D - Godot Asset Library It mimics the old behavior and extends it a bit.