Platformer: Box Push
In this article, I go over how to move push a box using a button press and colliding with it.
In the Player script we are using the OnControllerColliderHit function. The important thing we need to make sure we setup with the box or object we want to push is it needs…
a Rigidbody and Collider, so the Controller can detect the hit between the colliders and we can add a velocity to the Rigidbody attached to the box.
Make sure Use Gravity is on, Is Kinematic is off, and we freeze the rotation on X,Y,Z. Freezing the rotation will prevent the box from moving in any directions other than the way the player is pushing it.
An issue a ran into was the Push animation had the character inside of the box. This is took me some time to figure out with messing around with all of the animation settings, but the solution was increasing the size of the Box Collider.
This just leaves more space between the box and player, so when the animation plays it has the room for it to lean forward without going into the box.
In the Player script, we are using OnControllerColliderHit as stated before and this stores the collider of the object the controller is currently colliding with in a local variable “hit”. This method method is called every frame while the controller is moving.
This collision is detect when the character is moving and collides with the box, but I wanted to require the player to have to hold a button down to activate the push instead of just running into it. So, Input.GetKey is used which returns true when the whatever key you designate is held down.
This causes an issue where the player starts the pushing animation and as long as the push key is being pressed down, the player can continue to move left or right.
This took me a while to figure out, because I thought I could use OnCollisionEnter, OnCollisionStay, or OnCollisionExit but these are do not work with a Character Controller. I couldn’t use OnTrigger because that would allow the player to walk through the box since it disables the collider.
I needed a second condition along with the key being held down that could identify if the player is moving left or right. The _horizontalInput contains the raw value of the horizontal axis, which is either -1 when moving left or 1 when moving right.
So, if the horizontal input is not 0 then it is moving left or right but if it is 0, the player either stop moving or switch directions for a brief moment rending the condition false.
We check which object we are colliding with using the hit variable and checking the tag via the transform. We want to get a handle of the Rigidbody of the box we are colliding with and store it in the local variable rigidbody. It is important to perform a Null check to make sure the Rigidbody was cached.
We are going to create a new Vector3 that will determine which direction the box should be pushed and to determine that we will use the horizontal input that will either make the X = -1 (moving left) or the X = 1 (moving right). Using the rigidbody of the box we can add velocity to it by multiplying the push direction by a float variable (push power) that will determine how far it will be pushed. This variable is serialized so it can be adjusted in the Inspector. Lastly, we set the Push animation true.
Finally, when the player releases the push key, we set the Push animation false and the rest is nulled.
This took me a couple of days to figure out and it is so funny that something seems so simple can turn out to be more difficult than you thought. Chalk this up to more experience and on to the next challenge. Cheers!