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
MediumWalk the explorer with its CharacterController, so the wall stops it.
- In
Update(), buildVector3 movefromInput.GetAxisRaw("Horizontal")on x andInput.GetAxisRaw("Vertical")on z, timesspeed. - Set
move.y = -fallSpeed;and callcontroller.Move(move * Time.deltaTime);. - Then set
rend.material.colortoColor.greenwhilecontroller.isGrounded, elseColor.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
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 SwapPractice on your own: Unity playground