How to make WASD movement match camera

Godot Version

4.2.1

Question

I’m very new to Godot and Game dev as a whole and I was curious when I ran into an issue. Using the standard character movement script to move a character, when I eventually got character camera control using a pivot and camera, I couldn’t get the WASD keys to keep going forward, left, back and right. In this instance, W would send me to the left regardless of camera direction. Is there any way I could fix this?

If you’re using the CharacterBody3D default template, you probably have lines like these somewhere in your script:

var input_dir = Input.get_vector("move_left", "move_right", "move_forward", "move_back")
var direction = (transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()

Let’s say the player is pressing forward (W or up arrow on the keyboard), and nothing else. Then input_dir becomes the vector (0, -1).

We then take that vector and turn it into a 3D vector with a y coordinate of 0, that is, we turn it into (0, 0, -1). Godot defaults to using the negative Z axis as its forward direction, so this is a vector that points forward in global space.

However, we don’t want the character to always move along the global Z axis when the player is trying to move forwards. Our character should be able to rotate, and then “forwards” should mean “move in the direction the character is pointing”.

To accomplish this, we take our global space vector, which was (0, 0, -1), and multiply it with the characters transform.basis, which is a matrix describing how the character is rotated and scaled. Don’t worry too much about the math here - think of it as taking that (0, 0, -1) vector, and transforming it so it points along the characters -Z axis, instead of the global -Z axis.

Ok, so what’s happening with your camera, then? I don’t know exactly how you’ve set it up, but my guess would be that your camera pivot is a child node of your character, and that this child node is what actually gets rotated when you rotate your camera. This means that the CharacterBody3D doesn’t get rotated, but always points the same way, and therefore always moves the same direction in global space, no matter where the camera is pointing.

There are two ways of fixing this:

  1. use the camera pivot’s transform.basis to determine the movement direction:
  var direction = (pivot.transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()
  1. Change your camera logic, so that the actual CharacterBody3D node gets rotated, instead of a child node.
1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.