Moving character in third-person game

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

I’m trying to adapt the code from the third-person shooter demo to my own game, but I can’t get the character to move. The original script relied on the motion provided by the robot’s walking animation. But I don’t have anything animated like that (animation’s a bit too complicated for me). I’ve tried multiplying a certain amount by the vector on the motion variable, and have tried multiplying the z property of the vector which is suppose to move the character. But none of those have worked. Novosin (from the Godot Discord channel) has suggested using -transform.basis.z * speed. But I don’t know where to factor that in. My best guess is toying around with the horizontal_velocity variable, which is used with the velocity variable in the move_and_slide() function.

FWIW, here’s the working code. Note that this is overridden in the character’s script. I have also tried copying and pasting this code into the character’s script. But that didn’t work, either.

extends KinematicBody

## Code taken from the Godot third person demo's "player.gd" script.
# Source: https://github.com/godotengine/tps-demo/blob/3.1/player/player.gd

# Some constants
const CAMERA_JOYPAD_ROTATION_SPEED: float = 3.0
const CAMERA_X_ROT_MIN: int = -40
const CAMERA_X_ROT_MAX: int = 30

# Some constant speeds
const DIRECTION_INTERPOLATE_SPEED: int = 1
const MOTION_INTERPOLATE_SPEED: int = 10
const ROTATION_INTERPOLATE_SPEED: int = 10

var orientation = Transform()
var motion: Vector2 = Vector2()
var root_motion: Transform = Transform()
var velocity: Vector3 = Vector3()
var camera_x_rot: float = 0.0

onready var gravity: Vector3 = ProjectSettings.get_setting("physics/3d/default_gravity") * ProjectSettings.get_setting("physics/3d/default_gravity_vector")

# For testing purposes.
var joypad_index: int = 0

# These variables will be overridden in the character's script.
var camera_base: Camera
var camera_rot: Camera
var scene_root: MeshInstance
func _physics_process(change_in_process: float) -> void:
    var camera_move: Vector2 = Vector2( Input.get_action_strength("view_right") - Input.get_action_strength("view_left"),
    Input.get_action_strength("view_up") - Input.get_action_strength("view_down") )
    var camera_speed_on_this_frame: float = change_in_process * CAMERA_JOYPAD_ROTATION_SPEED
    rotate_camera( camera_move * camera_speed_on_this_frame )
    var motion_target: Vector2 = Vector2( Input.get_action_strength("move_right") - Input.get_action_strength("move_left"),
    Input.get_action_strength("move_back") - Input.get_action_strength("move_forward") )
    motion = motion.linear_interpolate( motion_target, MOTION_INTERPOLATE_SPEED * change_in_process )
    
    var camera_basis: Basis = camera_rot.global_transform.basis
    var camera_x: Vector3 = camera_basis.x
    var camera_z: Vector3 = camera_basis.z
    
    camera_x.y = 0
    camera_z.y = 0
    camera_x = camera_x.normalized()
    camera_z = camera_z.normalized()
    
    # When the character isn't aiming nor jumping, have them move around (and hopefully turn around, too).
    # For easy turning, let's use the complicated math concept of quaternions.
    var target: Vector3 = camera_x * motion.x + camera_z * motion.y
    if target.length() > 0.0001:
        var quaternion_from: Quat = Quat( orientation.basis )
        var quaternion_to: Quat = Quat( Transform().looking_at( target, Vector3.UP).basis )
        # Do some interpolation so as to reach the desired rotation.
        orientation.basis = Basis( quaternion_from.slerp( quaternion_to, change_in_process * ROTATION_INTERPOLATE_SPEED ) )
    
    ## This is where the animation would be updated. That has yet to be created
    
    var horizontal_velocity: Vector3 = orientation.origin / change_in_process
    velocity.x = horizontal_velocity.x
    velocity.z = horizontal_velocity.z
    velocity += gravity * change_in_process
    velocity = move_and_slide( velocity, Vector3.UP )
    
    # Clear out all of that saved up root motion (was applied to speed).
    orientation.origin = Vector3()
    # Let's ortho the orient.
    orientation = orientation.orthonormalized()
    
    scene_root.global_transform.basis = orientation.basis

func rotate_camera(move: Vector2) -> void:
    camera_base.rotate_y( -move.x )
    # The camera needs to be renormalized after a relative transform.
    camera_base.orthonormalize()
    camera_x_rot += move.y
    camera_x_rot = clamp( camera_x_rot, deg2rad( CAMERA_X_ROT_MIN ), deg2rad( CAMERA_X_ROT_MAX ) )
    camera_rot.rotation.x = camera_x_rot