Pushing Things
Part of the Building Real Games section of Coddy's Unity journey. Lesson 41 of 60.
A CharacterController never pushes anything: walk it into a crate with a Rigidbody and it stops as if at a wall. Instead, Unity calls OnControllerColliderHit(ControllerColliderHit hit) on the controller's own scripts for every collider a Move touches, the floor included, and the script decides what happens. hit.collider is what was touched, hit.moveDirection the direction of the Move that touched it, and hit.normal the direction its surface faces at the contact. This is Unity's own push script:
public float pushPower = 2f;
void OnControllerColliderHit(ControllerColliderHit hit)
{
Rigidbody body = hit.collider.attachedRigidbody;
if (body == null || body.isKinematic) return; // nothing to push
if (hit.moveDirection.y < -0.3f) return; // it is under our feet
Vector3 pushDir = new Vector3(hit.moveDirection.x, 0f, hit.moveDirection.z);
body.linearVelocity = pushDir * pushPower;
}Each return has a reason. The floor and walls have no Rigidbody, so body is null for them, and they are touched on almost every Move. A kinematic body moves only when its own script moves it, so a velocity does nothing to it. A Move that points steeply down touched something under the feet, and the crate the player stands on should not be shoved.
The push direction keeps only x and z, so a crate slides along the ground instead of being pressed into it. Setting linearVelocity, instead of adding a force, moves a light crate and a heavy one at the same pace; body.AddForce(pushDir * pushPower, ForceMode.Impulse) would push the heavy one less.
Challenge
MediumLet the player kick the balls it walks into.
- In
Kicker.cs, writevoid OnControllerColliderHit(ControllerColliderHit hit)and getRigidbody body = hit.collider.attachedRigidbody;. returnwhenbodyis null or kinematic, or whenhit.moveDirection.y < -0.3f(a ball underfoot).- Set
body.linearVelocityto the walking direction with y 0, timeskickPower, plusVector3.up * lift.
Press Play and walk into the red ball: it flies forward and up. Then Check.
Try it yourself
using UnityEngine;
public class Kicker : MonoBehaviour
{
public float kickPower = 6f;
public float lift = 4f;
// Kick the balls the player walks into
}
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