Menu
CoddyTech

CharacterController.Move

Part of the Building Real Games section of Coddy's Unity journey. Lesson 38 of 60.

A CharacterController is Unity's component for a walking character: a capsule that moves only when your script calls controller.Move(motion). motion is the distance to move this frame, so it is a speed times Time.deltaTime. Move slides the capsule along walls instead of through them, walks up slopes up to its Slope Limit (45 degrees) and steps onto ledges up to its Step Offset (0.3 units). It is not a Rigidbody: no forces, no gravity, no bounce, and nothing pushes it. It goes exactly where Move sends it, which is what tight game controls need.

Gravity is yours to add, and so is finding the floor. isGrounded is true when the last Move touched something below, so a move with no downward part never finds the floor. A Move shorter than the controller's Min Move Distance (0.001) does nothing at all, so a controller moved only sideways reports that it is not grounded as soon as it stands still. This courier walks with the arrows and presses down a little in every move:

public class Courier : MonoBehaviour
{
    public float speed = 6f;
    CharacterController controller;

    void Start()
    {
        controller = GetComponent<CharacterController>();
    }

    void Update()
    {
        Vector3 move = new Vector3(Input.GetAxisRaw("Horizontal"), 0f, Input.GetAxisRaw("Vertical")) * speed;
        move.y = -2f;   // always press down, so the floor is found
        controller.Move(move * Time.deltaTime);
        if (!controller.isGrounded)
        {
            Debug.Log("Off the ground");
        }
    }
}

The capsule keeps its Skin Width (0.08) away from what it touches, so a 2 unit tall controller on a floor at y = 0 rests at y = 1.08, not 1. And Move starts from where the physics last saw the controller, so a transform.position set on it can be undone by its next Move: to teleport it, set controller.enabled = false, move it, and enable it again.

challenge icon

Challenge

Medium

Walk the explorer with its CharacterController, so the wall stops it.

  1. In Update(), build Vector3 move from Input.GetAxisRaw("Horizontal") on x and Input.GetAxisRaw("Vertical") on z, times speed.
  2. Set move.y = -fallSpeed; and call controller.Move(move * Time.deltaTime);.
  3. Then set rend.material.color to Color.green while controller.isGrounded, else Color.red.

Press Play, walk into the wall and off the left edge: the explorer drops red and lands green. Then Check.

Try it yourself

using UnityEngine;

public class Explorer : MonoBehaviour
{
    public float speed = 4f;
    public float fallSpeed = 3f;

    CharacterController controller;
    Renderer rend;

    void Start()
    {
        controller = GetComponent<CharacterController>();
        rend = GetComponent<Renderer>();
    }

    void Update()
    {
        // Walk with controller.Move, then color the explorer by isGrounded
    }
}

All lessons in Building Real Games

Practice on your own: Unity playground