Pushing Things
Part of the Building Real Games section of Coddy's Unity journey. Lesson 40 of 56.
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
MediumKick the balls around the yard. The Player walks with a CharacterController (Walker.cs, ready). Write Kicker.cs, also on the Player. The Inspector sets kickPower (6) and lift (4).
- When the player walks into a body that can be pushed, set its
linearVelocityto the walking direction, flat along the ground, timeskickPower, plusliftstraight up, so the ball flies forward and up. - The ground and the post have no Rigidbody: skip them without an error.
- A ball under the player's feet is not kicked.
Press Play and kick the red ball, 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
}
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