Reputation: 259
I am an amateur developer starting a simple third person 3D game in Godot 3. I set up some controls that allow a KinematicBody (named Player) to move along the x and z axis based on WASD input. I also have a Camera as a child of the Player so the camera follows behind and rotates relative to the Player.
However when the Camera rotates, pressing forward still moves the Player along the global z axis! I would imagine that when the player rotates and you press forward, the player should move away from the camera.
Is there a built in way to move along an x or z axis that is based on the rotation of the Player? i.e. pressing forward translates along a local negative z axis, making it move forward locally.
I have read the documentation for Transform()
and Basis()
, and it seems related but is pretty unclear; or at least beyond my skill/understanding.
Upvotes: 2
Views: 9871
Reputation: 259
I did some research, and this is what I found:
Godot (and most other 3D applications) do not use what are called Euler Angles for rotations, (which can be visualized by the rotation 3D gizmo in the editor) for performance and technical reasons. Instead, it uses Basis vector transformations.
Instead, imagine you make a 2D object and give it 2 vectors that are 90 degrees apart and the same length; one on the x axis and one on the y axis. These are the object's "local" x and y coordinates. When rotating the object, instead of rotating the object itself, it changes the coordinates of the terminal points of the vectors in a way that keeps them 90 degrees apart and the same length causing its local x and y to "rotate". Sort of like if you make an 'L' with your hand, place it on the table, and rotate it back and forth. The rotation is not stored in the angle of your hand, it is stored in the position of your fingertips.
The same thing happens in 3D, but with a third vector added along the z axis. Most importantly of all this however, is that you can refer to these vectors and use them by doing transform.basis.[x,y,z]
. In your case, you already have something like:
movement = Vector3(0,0,0)
if Input.is_action_pressed("ui_up"):
movement.z -= 1
However, instead of moving along an arbitrary vector, you should add whatever your basis z vector is to your movment vector:
movement = Vector3(0,0,0)
if Input.is_action_pressed("ui_up"):
movement -= transform.basis.z.normalized()
I normalize the vector to get rid of any scaling. To learn more about adding vectors and other vector maths, see this.
For more extensive information, see this.
Upvotes: 6