Menu
CoddyTech

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 icon

Challenge

Medium

Kick 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 linearVelocity to the walking direction, flat along the ground, times kickPower, plus lift straight 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
}
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Building Real Games