Godot 4 How to do third person 3d movement relative to camera angle

1.6k views Asked by At

I've created a very simple 3d platformer character to move around a basic level. I've added a springarm with a camera as a child of the Playerbody3D, which is rotated using gamepad controls. But I cant make the player's movement relative to the camera angle, at least not properly

Here's what I have so far for the player's movement (I've omitted some stuff like jumping)

extends CharacterBody3D

@export var move_speed : float = 4.8
@export var jump_force : float = 12.0
@export var camera_speed : float = 2.0
var gravity : float = 20.0
var facing_angle : float
var controller_sensitivity = 1

@onready var model : MeshInstance3D = $Mesh
@onready var camera : SpringArm3D = $SpringArm

func _physics_process(delta):
    var input = Input.get_vector("move_left", "move_right", "move_forward", "move_backward")
    var relative_input = get_camera_relative_input(input)
    var dir = Vector3(relative_input.x, 0, relative_input.y)
    
    
    velocity.x = dir.x * move_speed 
    velocity.z = dir.z * move_speed 
    move_and_slide()
    
    
    
    ###Camera rotation code
        var camera_input = Input.get_vector("camera_left", "camera_right", "camera_up", "camera_down")
    var camera_x_move = camera_input.x * camera_speed
    var camera_y_move = camera_input.y * camera_speed
    if camera_input != Vector2.ZERO:
        camera.rotate_y(deg_to_rad(-camera_x_move) * controller_sensitivity)
        camera.rotate_x(deg_to_rad(-camera_y_move) * controller_sensitivity)
        camera.rotation.x = clamp(camera.rotation.x, deg_to_rad(-40), deg_to_rad(-10))
        camera.rotation.z = 0


func get_camera_relative_input(input) -> Vector3:
    var cam_right = camera.global_transform.basis.x
    var cam_forward = camera.global_transform.basis.z
    # make cam_forward horizontal:
    cam_forward = cam_forward.slide(Vector3.UP).normalized()
    # return camera relative input vector:
    return cam_forward * input.y + cam_right * input.x

The springarm is a direct child of the CharacterBody3D this code is attached to, and the camera is a child of the springarm

currently when the program runs, the character can move left and right but not forward or back

1

There are 1 answers

0
Theraot On

This might be a partial answer (i.e. it could improve the situation, but there might be other problems that I'm not aware of).

The only thing that I notice is that you make cam_forward horizontal but not cam_right. So you can make them both horizontal, like this:

func get_camera_relative_input(input:Vector2) -> Vector3:
    var cam_right := camera.global_transform.basis.x
    var cam_forward := camera.global_transform.basis.z

    cam_right = cam_right.slide(Vector3.UP).normalized()
    cam_forward = cam_forward.slide(Vector3.UP).normalized()

    return cam_forward * input.y + cam_right * input.x

Although, I suggest you make the result horizontal instead:

func get_camera_relative_input(input:Vector2) -> Vector3:
    var cam_right := camera.global_transform.basis.x
    var cam_forward := camera.global_transform.basis.z

    var result := cam_forward * input.y + cam_right * input.x

    return result.slide(Vector3.UP).normalized()