Make the camera look at an object

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Sakura37

When the player enters an area, i made him stop moving and i also made an object showing at the same time. The question is, how can i make the camera (after the player stops) glide slowly to my object position, and after it got into position → make the object appear? And after the object appears, the camera glides faster to the player.
(*The camera is a child of my player)

:bust_in_silhouette: Reply From: Bernard Cloutier

Making your camera a child of your player is a quick and easy way to have a camera precisely follow him, but it makes focusing the camera on other things difficult.

I’d suggest taking the camera out of the player and adding a target variable on the camera script. This will require you to rethink how that camera moves around though.

something like this:

extends Camera2D

var target
var speed

func _process(delta):
    var target_dir = (target.position - self.position).normalized()
    position += speed * target_dir * delta

This would let you set the target and camera speed to fit your needs. However, this implementation introduces the risk of having your target move faster than the camera, so you probably want to make sure the camera “sticks” to the target, whether by adding a “is_centered” bool that makes camera’s position always take the target’s position (ignoring speed and delta), or by adding some sort of boundaries to ensure the target doesn’t leave the camera’s viewport. To help with that last point, you could check out this video (although in this case the camera is a child of the player):

Thank you! I actually used your advice and took the camera out of the player, it was easier that way. I took Magso’s code and combined it with your advice.

Sakura37 | 2020-02-25 20:35

:bust_in_silhouette: Reply From: Magso

Edit - 2D: Use lerp to interpolate the global position to the target’s global position.

onready var target = get_node("path/to/node")
var speed : float

func _process(delta):
    set_global_position(lerp(get_global_position(), target.get_global_position(), delta*speed)

For 3D: You could replace your camera with an InterpolatedCamera, or use a lerp. Because the camera is a child of the player you will need to use global_transform.origin, and InterpolatedCamera (from my experience) seems to use transform.origin instead. By all means try the InterpolatedCamera, if that doesn’t work here’s a lerp script.

onready var target = get_node("path/to/node")
var speed : float

func _process(delta):
   global_transform.origin = lerp(global_transform.origin, target.global_transform.origin, delta*speed)
   var current_rotation = Quat(global_transform.basis)
   var next_rotation = current_rotation.slerp(Quat(target.global_transform.basis), delta*speed)
   global_transform.basis = Basis(next_rotation)

the script is for the camera that is a child to the player or for a camera which i include in the scene?

Sakura37 | 2020-02-25 17:57

It doesn’t matter because it’s using global_transform not transform which would be local space.

Magso | 2020-02-25 18:16

It says "can’t get index ‘basis’ on base ‘Transform2D’ " at the second line of the process function.

Sakura37 | 2020-02-25 18:33

Oooohhhh 2D? *facepalm
My answer is for 3D, I’ll edit it for 2D as well. I should’ve known by the “camera2d” tag.

Magso | 2020-02-25 19:48

Thank you so much for your patience and help! I was having difficulties with the camera being a child of the player(the player is an instanced scene) and i couldn’t manage to change the target.
But I assigned a camera to the scene and it worked! And it’s easier to code if the camera is a child of the scene, not a child of the player.

Sakura37 | 2020-02-25 20:33