CharacterController.Move
Part of the Building Real Games section of Coddy's Unity journey. Lesson 37 of 56.
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
MediumThe explorer stands on a stone platform with a wall at the back and a drop on the left. Write Explorer.cs on the Player, which has a CharacterController. The Inspector sets speed (4) and fallSpeed (3), and Start() already finds the controller and the explorer's Renderer.
- The arrows (or WASD), read with the raw axes, walk it with
controller.Moveatspeedunits a second: left and right along x, up and down along z. The wall must stop it. - Every move also goes down at
fallSpeedunits a second, so the explorer stays on the platform and drops off its edge. - While the controller is grounded, the explorer is
Color.green; while it is not,Color.red.
Press Play, walk into the wall and off the edge, 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
}
}
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Building Real Games
2Buttons and Screens
Buttons and onClickLambdasWiring in the InspectorPanels On and OffHealth BarsRecap: Upgrade Shop5Saving with PlayerPrefs
Save a NumberLoad with a DefaultHigh ScoreSave SettingsRecap: Coins in the Bank8Character Controller
CharacterController.MoveGravity by HandJumpingPushing ThingsMove Where You LookRecap: Double Jump3The Game Manager
One Script Runs the GameThe SingletonGame StatesSwitching on the StateRecap: Round Manager6Project: Endless Runner
Three LanesObstacles Ahead9The New Input System
Two Input SystemsKeyboard and MousePressed This FrameInput ActionsRecap: Input Swap