Make Camera3D face the same direction as RigidBody3D

Godot Version

4.2.2

Question

I’m trying to create a game like Super Monkey Ball, so I have a ball (RigidBody3D), some platforms (StaticBody3D) and a Camera3D and I’m currently having 2 problems in the development.

At the moment the Camera is controlled by a script that changes his position just by editing the Ball’s position in order to create an offset/distance effect.

Now I’m trying to edit the Camera script in order to make the Camera always face the direction in which the ball is going towards, but I just can’t find a way to make it work.

I’ve tried using the Phantom Camera addon, using “look_at”, setting the y axis of the camera as the one of the target ball, making the camera a child of the target ball, but nothing worked so far.

Thanks in advance.

Script

var DIRECTIONAL_VELOCITY_COEFFICENT = 0.25
var SHIFT_DOWN_ENABLED = true
var GOING_BACK_ENABLED = true

func _physics_process(delta: float) -> void:
	#$Camera3D.look_at($RigidBody3D.position)  
	$Camera3D.position.x = $RigidBody3D.position.x 
	$Camera3D.position.y = $RigidBody3D.position.y + 1.6
	$Camera3D.position.z = $RigidBody3D.position.z + 2.7  
	
    # Going out of bounds
	if $RigidBody3D.position.y < -25:
		$RigidBody3D.freeze = true
		$RigidBody3D.position = Vector3(0,0,0)
		$RigidBody3D.freeze = false

func _input(event: InputEvent) -> void:   
	""" 
	if event.is_action_pressed("jump"):
		jump()
	if event.is_action_pressed("left"):
		turn_left()
	if event.is_action_pressed("right"):
		turn_right()
	if event.is_action_pressed("front"):
		go_front()
	if event.is_action_pressed("back"):
		go_back()
	"""
	
	if event is InputEventKey:
		if event.pressed and event.keycode == KEY_ESCAPE:
			get_tree().quit()
		if event.pressed and event.keycode == KEY_LEFT:
			turn_left()
		if event.pressed and event.keycode == KEY_RIGHT:
			turn_right()
		if event.pressed and event.keycode == KEY_UP:
			go_front()
		if event.pressed and event.keycode == KEY_DOWN and GOING_BACK_ENABLED:
			go_back()
		if event.pressed and event.keycode == KEY_SHIFT and SHIFT_DOWN_ENABLED:
			jump_down()
		
	if event.is_action_pressed("jump"):
		jump()

func jump():
	$RigidBody3D.apply_impulse(Vector3(0, 30, 0))
func turn_left():
	var vel = $RigidBody3D.linear_velocity.x
	$RigidBody3D.apply_impulse(Vector3(-3 - (abs(vel) * DIRECTIONAL_VELOCITY_COEFFICENT), 0, 0))
func turn_right():
	var vel = $RigidBody3D.linear_velocity.x
	$RigidBody3D.apply_impulse(Vector3(3 + (abs(vel) * DIRECTIONAL_VELOCITY_COEFFICENT), 0, 0))
func go_front():
	$RigidBody3D.apply_impulse(Vector3(0, 0, -3))
func go_back():
	$RigidBody3D.apply_impulse(Vector3(0, 0, 3))
func jump_down():		
	$RigidBody3D.apply_impulse(Vector3(0, -30, 0))

You can use the linear_velocity of the ball to point in the direction to look at.

There are probably many ways to go about this, but you can use this vector to get the angle between it and the global front face vector of the camera.

And with this information rotate the camera.

You can add the linear_velocity to the ball’s global position to get a global position to look at. This position can be push-out, or pull-in, if you multiply the velocity vector with a scaling value.