Menu
CoddyTech

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 icon

Challenge

Medium

Let the player kick the balls it walks into.

  1. In Kicker.cs, write void OnControllerColliderHit(ControllerColliderHit hit) and get Rigidbody body = hit.collider.attachedRigidbody;.
  2. return when body is null or kinematic, or when hit.moveDirection.y < -0.3f (a ball underfoot).
  3. Set body.linearVelocity to the walking direction with y 0, times kickPower, plus Vector3.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

Practice on your own: Unity playground