I have a very basic third person controller:
func _physics_process(delta):
vel.x = 0
if Input.is_action_pressed("move_forward"):
vel.x += SPEED * delta
if Input.is_action_pressed("turn_left"):
rotate_y(deg2rad(ROTATION_INTENSITY))
move_and_collide(vel)
However on rotating and then moving forward, the player will move forward on the x axis instead of the direction the player is pointed. How do i fix this? Thanks in advance!
Your KinematicBody
is an Spatial
, and as such it is positioned by a Transform
.
You can get the Transform
from the parent Spatial
(or the root of the scene tree if there is no parent Spatial
) from the transform
property.
And you can get the Transform
from root of the scene directly from the global_transform
property.
The Transform
has two parts:
Together they encode a coordinate system. In particular basis
has three vectors that hold the direction and scale of each of the axis of the coordinate system. And origin
has the position of the origin of the coordinate system.
Now, Godot's coordinate system in 3D is right handed with UP = Y and FORWARD = -Z. You can confirm this with the constants Vector3.UP
and Vector3.FORWARD
. Also notice this differs from Unity and Unreal which are left handed.
Ergo, if you want the direction of one of the axis, you can get it form the basis of the global transform. Like this:
var forward := -global_transform.basis.z
var backward := global_transform.basis.z
var left := -global_transform.basis.x
var right := global_transform.basis.x
var down := -global_transform.basis.y
var up := global_transform.basis.y
You could use those to build your velocity in global coordinates, for example:
velocity += global_transform.basis.x * SPEED
Alternatively, you can convert vectors from local to global space with to_global
(and from global to local with to_local
) so you can do this:
var forward := to_global(Vector3.FORWARD)
var backward:= to_global(Vector3.BACKWARD)
var left := to_global(Vector3.LEFT)
var right := to_global(Vector3.RIGHT)
var down := to_global(Vector3.DOWN)
var up := to_global(Vector3.UP)
This also means you may build your velocity in local coordinates, and convert it to global coordinates at the end:
move_and_slide(to_global(velocity))
And just to be clear, move_and_slide
expects global coordinates.
I will also point out that it is possible to rotate a vector with rotated
and project a vector onto another with project
.