How to move the player's vision in a FPS during a cutscene

Godot Version

Godot 4.2

Question

I have a scene where I want the player to freeze ( I can do this part) turn around to be able to see the flame wall coming behind them. My issue is using an animation player to turn the player around 180 degrees wont work if the player is looking to the side or at the floor. I need a way to calculate the position the camera is in and where I want it to end up (I can somewhat do this part) but the hardest part for me is to actually move the camera. I was able to move it but it’s a snap movement and I’m not able to control the speed of the turn or do any type of easing with the camera movement. HELP!

A Tween is good for any animation where there are uncertain factors like where the camera is currently looking.

If you know the global angle you want to end at, something like this could work for you

var camera_tween := $Camera3D.create_tween
var final_rotation := Vector3(0.0, -PI, 0.0)
camera_tween.tween_property($Camera3D, "rotation", final_rotation, 1.0)
1 Like

This is how I would do it:

  1. Create a cutscene camera with an animation player.
  2. Make your animation with the camera.
  3. Move the cutscene camera to the exact position and rotation as the player camera.
  4. Make the cutscene camera active.
  5. Use a tween like @gertkeno said to rotate the camera between the current position and the start of your animation position.
  6. Run the animation.
  7. At the end of the animation, set the player camera to the rotation of the cutscene camera.
  8. Tween the cutscene camera so it moves to the position of the player camera.
  9. Make the player camera active again.

You could do all this with the player camera. The reason I would choose to create a second camera is your player camera acts as a reset with every saved value to go back to. It will help with debugging if say you were to change the POV and forgot to change it back, you’d see the snap easily and be able to debug. Also then the cutscene camera and animation can be stored separately from the player and you can reuse it for other cutscenes.

I have looked at using tween. I think you are right in that it is how I want to do it. My problem is depending on where the player is standing the “global angle” I want it to end at will be different. What works perfectly for me is the look_at() except I don’t see a way to make it not snap to where I want it to look. Thank You for you’re time replying to me. Hopefully what I’m saying makes sense I’m relatively new to all this.

I like using a “cutscene camera” because like you said going back to reset of the saved camera with all the stored values is very nice. My problem still comes down to step 5. I am unsure how to make the camera rotate from a random spot and angle the player may be in or looking at to another random value that would be the angle the camera needs to be at depending on where the player was standing. So if the player is directly in front of the wall it would be 180 degree turn where if they were on the left side of the room they would only need to turn 120ish degrees to look directly at the wall. I hope I’m making sense and thank you so much for the reply!

Tweens can handle that too, any uncertain value can be interpolated with a tween. If you know what direction the camera need to end up facing you could punch that rotation in manually, like my sample with final_rotation, or you could use Basis.looking_at and it’s Basis.slerp.

This is exactly what a Tween is built to do.

Yeah you’re making sense.

So @gertkeno gave you most of what you need. Assuming you have an animation called “LookCutscene”, and a “RESET” animation setup. (It’s a single frame that resets your animation player - in this case you want it to have the values for the beginning of your cutscene.) Then for step 5 it would be something like:

@onready var player_camera = $PlayerCamera
@onready var cutsene_camera = $CutsceneCamera
@onready vat cutscene_animation_player = $AnimationPlayer

func start_cutscene() -> void:
	#play the RESET animation to reset the camera
	cutscene_animation_player.play("RESET")
	var camera_tween := cutsene_camera.create_tween()
	var final_rotation := cutscene_camera.global_rotation
	var final_position := cutscene_camera.global_position
	cutscene_camera.global_rotation = player_camera.global_rotation
	cutscene_camera.global_position = player_camera.global_position

	cutscene_camera.current = true
	camera_tween.tween_property(cutscene_camera, "rotation", final_rotation, 1.0)
	camera_tween.tween_property(cutscene_camera, "position", final_rotation, 1.0)
	cutscene_animation_player.play("LookCutscene")

I appreciate all the responses. I think my lack of knowledge in Godot isn’t allowing me to figure out how to make it work the way you both were suggesting. I was able to find a few more people on reddit who also had this problem and they couldn’t figure it out either. I did however, figure out an outside of the box solution.

I created just a regular node_3d that is a child of my camera/head. I called it “look_at_node” I use that to perform the “look_at()” function then I use it’s global rotation for my tween.

look_at_node.look_at(marker_3d.global_position)
var tween = head.create_tween()
var final_rotation = look_at_node.global_rotation
tween.tween_property(head, "global_rotation", final_rotation, 1.0).from_current()
1 Like

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