Pushing Objects with Player in 2.5D Platformer Prototype with Unity 2021

In this article we’ll give the player character the ability to push certain game objects around the scene.

To do this, we’ll be using OnControllerColliderHit() as we did in the previous article for wall jumping.

We’ll have to be careful not to break our wall jumping implementation as we go!

Unity’s Documentation Provides an Example
Luckily for us, Unity’s documentation for the OnControllerColliderHit() method provides a code example for this use-case.

Essentially, we’ll want to use the hit information to determine if the other game object has a rigidbody and does not have isKinematic set to true.

We’ll also want to check that the character is more or less next to the game object and that only push game objects from the sides.

From there, we’ll calculate and apply a push velocity to the other game object to move it.

The provided scene I’m using already has a box game object with rigidbody attached.

If you are working from scratch, create one and place it in your scene.

We’ll want to also set some constraints on our box’s rigidbody as shown above.

PlayerController Class/Script — OnControllerColliderHit() Method
The code we implement in our OncontrollerColliderHit() method is basically the same as the example.

I’ve just wrapped it in an if statement instead of using multiple return statements.

I did use a return statement in the JumpableWall case though as we don’t want to push around our walls!

I’ve also used our _playerVelocity class variable to determine force.

If we did not reduce the _playerVelocity.x value when applying push force, we would essentially be claiming that the player is either so strong or has so much mass (the e=mc2 sort) that there was only a tiny amount of resistance from the object pushes.

By halving that force I’m getting a better physics interaction in my opinion.

If we run our game, we can see the box behavior is working as expected.

I want to note two things.

First, if we didn’t want every rigidbody game object to be affected, we would tag the game objects that should be movable and use ComparTag() in our code logic.

Second, I can see my player is sticking to the ceiling again!

The first thing I needed to do was get the reset of _playerVelocity.y in my DeterminePlayerVelocity() method moved down to just before the gravity is applied and MovePlayer() is called.

The jumping if/then was overriding my override.

In OnControllerColliderHit(), I was only assigning _wallCollisionNormal when the hit game object was a jumpable wall and that is not the case with a ceiling.

So I simply added a not isGrounded check and assigned the value there.

I might as well move the assignment above the jumpable wall logic and then just remove the second assignment in that logic.

I’ve left it as commented out in the image above for ease of visualization, but it has been deleted from the class/script.

This is also true of commented out code shown in the DeterminePlayerVelocity() method from the image earlier in this article.

As a rule of thumb, expect this to be the case any time I use an image to explain code refactoring.

Now if we run the game, we can see that the player bounces off the ceiling.

I’ve made sure the downward force isn’t so much that I can’t jump over the box in a constrained area though.

I just wanted to note that I found this bit of code reference.

This could be an easier way to check sides versus bottom than the hit.normal.

I settled on the -20f value for bouncing off the ceiling.

Physics Glitch
Wow, did I spend a lot of time tracking down this issue.

The key was bumping up the Skin Width on Character Controller component from 0.08 to 0.1.
Or so I thought.

Returning the Skin Width to 0.08 with the Capsule Collider disabled also seemed to work correctly.

Disabling the Capsule Collider component is the real solution.
Apparently, we have two colliders interacting from the player game object with other game objects.

And apparently, the Character Controller has its own collider, but it doesn’t make that very clear!

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store