OnCollisionEnter Vs. OnTriggerEnter. How are they different and when should you use them?
Objective: To understand the differences between these two functions, and how they are applied in Unity programming.
Collider components are attached to GameObjects. They are invisible to the Player, but they typically are similar in shape as the GameObject itself. Think of it as some sort of sensory layer on the object like the skin on a human. These can be of primitive or complex shape. When these are paired up with a Rigidbody component, they allow the detection of collisions between objects.
There are basically two types of collisions:
Hard surface collision: such as hitting a wall, a bullet impact,…As long as one of the objects has a non-kinematic Rigidbody component attached (which means they derive their resulting movement not from physics, but from scripts), the Unity physics engine will come into play and determine how the colliding objects will behave. The MonoBehaviour class in Unity uses collision detection to call the OnCollisionEnter() function. If both objects are kinematic, then the OnCollisionEnter() function will not be called.
Trigger collision: powerup, coin collection,… There’s no physics force applied. You pass through the object and it triggers an event. If the object is set as a trigger (setting the Is Trigger property to TRUE) and its collider enters the space of another collider on a different object, the scripting system can initiate an event using the OnTriggerEnter() function. The GameObject will not behave as a solid object and simply let the other colliders pass through their space. When looking for trigger detection, both objects can have their Rigidbody components set to “Is Kinematic”.
This can get somewhat confusing at times. Thankfully, Unity documentation provides us with a clear Collison action matrix table:
So, when would you like to use either function? Think of OnCollisionEnter() as a function to deal with “collision” as an impact between two solid objects, such as a sphere bouncing off a plane, a car colliding against a wall, or a bullet impact pushing your character back. Upon detecting the collision between the objects, they would be subjected to the physics as set in the Unity world environment, and a script could be called to deal with the repercussion of the impact (think damage, points, destruction of an object, instantiation of an explosion,…).
OnTriggerEnter() can be visualized as setting off an alarm. The two objects that collided will not bounce off each other. There will be no physical interaction affecting their direction or velocity. They will simply allow Unity to detect a collision and initiate an event if scripted to do so.
In the example below, all three objects (Sphere, Plane, and Cube) have Rigidbody components attached. None are using gravity. The Plane has “Is Trigger” set to TRUE. The Sphere has a script attached which moves it downwards at a nice slow rate of 2 m/s. Once it collides with the Plane, the trigger is detected and the message “The Sphere is coming!!!” is sent to the console. Upon reaching the Cube, the Sphere collides and both objects have their position/trajectory and velocity (Cube only) altered as a result, along with another console message “You hit something!”.
In summary, both functions are equally valuable and can further be tailored by adjusting the timing of the collision (OnCollisionEnter, OnCollisionStay, and OnCollisionExit) of the trigger (OnTriggerEnter, OnTriggerStay, OnTriggerExit).