Goal
This lesson introduces a classic beginner movement controller. The focus is not on advanced physics, but on understanding how keyboard input becomes motion in the scene.
Use Input.GetAxisRaw and a CharacterController to build readable WASD movement.
Lesson Overview
This lesson introduces a classic beginner movement controller. The focus is not on advanced physics, but on understanding how keyboard input becomes motion in the scene.
25-35 min / Beginner. Keep the first pass small, then change one thing on your own.
WASD or arrow keys move the player.
Before You Start
The lesson is easiest to follow when you know what should happen on screen, which control or editor action triggers it, and what counts as done.
This lesson introduces a classic beginner movement controller. The focus is not on advanced physics, but on understanding how keyboard input becomes motion in the scene.
Read horizontal and vertical input from Unity's standard input axes.
WASD or arrow keys move the player.
Keyboard movement is one of the first patterns many learners want to build because it makes a 3D scene feel interactive right away. Unlike a passive demo, movement lets you test your own input, feel the response, and judge whether the controls seem stable or awkward.
This lesson focuses on a readable approach using CharacterController and Input.GetAxisRaw. That combination is practical for beginners because it keeps movement code explicit. You can clearly see where input comes in, how a movement vector is created, and how it becomes actual motion in the scene.
using UnityEngine;
public class KeyboardMove3D : MonoBehaviour
{
[SerializeField] private float moveSpeed = 5f;
[SerializeField] private CharacterController controller;
private void Update()
{
float x = Input.GetAxisRaw("Horizontal");
float z = Input.GetAxisRaw("Vertical");
Vector3 move = new Vector3(x, 0f, z).normalized;
controller.Move(move * moveSpeed * Time.deltaTime);
}
}This is a classic beginner bug. When both axes are pressed, the resulting vector is longer than moving in only one direction. Normalizing the vector fixes that by keeping the total length under control.
If movement seems rotated relative to the model, check the player's forward orientation in the scene. Some imported models are not aligned the same way as Unity's default forward direction.
Rotation only makes sense when the move vector is large enough. If you try to rotate toward a tiny or zero vector every frame, the result can feel jittery or undefined.
It keeps the first version easier to reason about. You can focus on input and motion without immediately solving advanced Rigidbody setup, drag, force balancing, or collider behavior.
GetAxis gives smoothed values and can feel nicer, but GetAxisRaw is easier to explain at the beginning because the input jumps cleanly between simple values.
Yes, and that is a strong next step. Camera-relative movement is common in third-person games, but it adds a second layer of vector reasoning, so it is often better as the follow-up lesson.
Not because Rigidbody is bad, but because it introduces more variables. The simpler path first usually helps learners understand the intent of their controls before adding physics complexity.