How to use collision functions in Unity: OnCollisionEnter

Collisions play an important role in computer games. This is probably not specific. Mechanicsand the bulk layer interactions between game objects.

In this article (and possibly a series of articles later) we’ll take a look at how to work with collisions in Unity, how to catch and handle them in code, dive deeper into the topic and try to answer frequently asked questions.

It is assumed that you already know Unity and C# at a basic level: you looked at one or two tutorials, read a couple of articles, managed to poke something in the engine yourself and want to keep developing

How does the collision system work? What are colliders?

Unity’s collision system is powered by Colliders.

A collider is a component that represents the invisible “boundaries” of an object.

Often they coincide with the shape of the object itself (as in the real world), although this is not necessary.

Unity supports a variety of collider shapes:

  • BoxCollider – the shape of a cuboid

  • SphereCollider – sphere

  • CapsuleCollider – a capsule (mathematically, a spheroid or ellipsoid of revolution)

  • MeshCollider – a custom 3D mesh shape that matches the shape of the mesh itself.

  • BoxCollider2D – rectangle

  • CircleCollider2D – circle

  • PolygonCollider2D – custom 2D sprite shape that repeats the shape of the sprite itself.

Again, colliders set the boundaries of objects that are used in the calculation of physics. For example:

The cube lies on the table: both the cube and the table have borders, so they do not pass through each other.

The hero was hit by a stray bullet: we will fix this and reduce his health.

The hero runs and runs into a wall: he cannot run through the wall because they both have boundaries.

triggers

Triggers are the same colliders. Seriously, just one tick on any collider component turns it into a trigger!

But triggers are “physically transparent”. In other words, objects marked as triggers* are not solids and skip any other body through myself.

Triggers are mainly used as some kind of zones, or areas, hitting which entails some consequences. For example:

The poison gas room is one big trigger: the hero walks through it without physical interaction, but the entire time the hero is inside, he takes passive damage from the poison.

The enemy’s line of sight is also a trigger: when the hero is in this zone, the enemy sees him and shoots at him.

The door opening zone can also be a trigger: let’s place this zone next to the door. If the player presses the E button while inside this zone (i.e. close enough to the door), then it opens, otherwise it does not.

Collision Handling

The most interesting and important: how to find out correctly from the code that a collision has occurred and handle it?

To do this, the Unity developers rolled up a whole set of functions for us. I propose in practice to consider in detail how one of them works, and then we will discuss others using its example.

By link you can download the project to follow the article: https://drive.google.com/file/d/1mh3OJd3VtdKA7BG7X9bTuwA5PxGyn6x4/view?usp=sharing

So, before you is a scene with a large platform, a cube and a ball (as well as a little lighting). Let’s make it so that when the ball falls on the cube, the latter is destroyed.

let’s hang colliders on objects: on the ball – SphereColliderper cube – BoxCollider. Besidesboth objects addm component Rigidbody.

You probably already know that Rigidbody is a component that adds physics to the object. It is thanks to him that the ball will fall, and when it comes into contact with the cube, it will bounce off it.

Let’s create a Ball.cs script in the Scripts folder. We’ll hang it on a ball right away so that we don’t forget it later. You need to add the following code to the script:

public class Ball : MonoBehaviour
{
    private void OnCollisionEnter(Collision collision)
    {
        print("Collision detected");
    }
}

The OnCollisionEnter function will be called automaticallywhen the ball touches something. Call her anywhere no need.

Try running the code and make sure that the correct phrase is printed to the console when the cube is hit.

The only argument collisionstores collision information. In particular, it contains the variable gameObjectin which the object is stored, which a collision has occurred.

Try to replace print("Collision detected") on print(collision.gameObject) and you will see that in the event of a collision, information about our cube is displayed in the console:

Cube (UnityEngine.GameObject)

Now, instead of the print, we will delete this same cube:

private void OnCollisionEnter(Collision collision)
{
    Destroy(collision.gameObject);
}

The Destroy() function allows you to destroy an object. The first argument it takes is the object itself (in our case, the cube), and the second – optionally – after how many seconds the destruction should occur.

Save the script and run the game to see how the ball destroys the cube first, and then – suddenly – and the floor! Yes, because the floor is the same object that has a collider (you can check:)

How to make the floor not be removed?

The most correct would be to hang a special tag on the floor, by which it can be distinguished from other objects. To do this, select the gender, create a new tag in the inspector by clicking “Add Tag…” and name it Floor. After that, select the gender again and attach this tag to it (it will appear in the list).

Now let’s add a check to the code to destroy only those objects that do NOT have the “Floor” tag:

private void OnCollisionEnter(Collision collision)
{
    if (collision.gameObject.tag != "Floor")
    {
        Destroy(collision.gameObject);
    }
}

Profit!

(Well, or you could leave everything as it is and say that this is not a bug, but a feature)

Let’s move on to other features

Don’t close the project. Replace the written function with this one:

private void OnCollisionStay(Collision collision)
{
    print("Objects are colliding");
}

When you run the project, you will see that the string is printed to the console every single frame.

The OnCollisionStay function fires every* frame when objects touch even slightly.

And the OnCollisionExit function fires only one frame – when the touch has stopped.

* Actually, not really: it’s a physical function and it works every time physical frame. One-line childish explanation: Unity handles physics separately from non-physics: physics is only handled in “physical frames”, which are Not all.

Back to triggers

Let’s discuss triggers now. You can try checking the “Is Trigger” checkbox in the component SphereCollider at ball. Having started the game, you will instantly understand what triggers are, if you have not yet got an idea 🙂

Go now to another scene, TriggersLesson, in the “Scenes” folder. When you start the game, you will see that you are playing for a capsule, which I was too lazy to turn into a normal hero 🙂

Let’s make it so that when entering the burning zone, our hero increases, when he is in it, he blinks, and when he exits, he decreases again.

Please note that this area is trigger (you can verify this, the IsTrigger checkbox is checked in the collider component), and therefore we will use trigger functions. Find the file in the Scripts folder Player.cs. It already contains some functions that are responsible for moving the player. Add a few more features at the end:

private void OnTriggerEnter(Collider other)
{
    if (other.gameObject.tag == "FireZone")
        transform.localScale *= 2;
}

Note that trigger functions NOT take as an argument object of type Collision, i.e. collision information, since there was no collision. Instead, they simply store a reference to the collider component of the object they collided with. In our case, since the script hangs on the hero, the variable otherrefer to the zone itself.

We check if it is our trigger and increment the object.

If you leave everything as it is, then you can enter and exit the circle several times and reach gigantic sizes. Let’s fix it 🙂

private void OnTriggerExit(Collider other)
{
    if (other.gameObject.tag == "FireZone")
        transform.localScale /= 2;
}

Similar function: we check if we really entered the zone and reduce the player.

private void OnTriggerStay(Collider other)
{
    if (other.gameObject.tag == "FireZone")
    {
        Color color = new Color(Random.Range(0f, 1f), Random.Range(0f, 1f), Random.Range(0f, 1f));
        GetComponent<MeshRenderer>().material.color = color;
    }
}

This function will create a multi-colored random flicker. We are simply changing the color of the material applied to the mesh. To do this, we refer to the component MeshRenderer.

By the way, each frame use GetComponent() – bad practice. This hits performance hard. Therefore, the components cost cache. I have already done this in the 9th and 14th lines: announced variable and initialized it in function Awake.Now just replace the call GetComponent<MeshRenderer>() to a variable _mesh.

By the way, I also cached the componentRigidbodywhich I also need every frame to move the character.

I feel like this article is already getting quite long, so I’ll describe how to use the 2D versions of the collision functions in the next article (if there is one…)

DZ:

As a practice, I suggest you work with both scenes. For example, you can do the following:

  1. In the first scene, instead of scripting a ball, write a script for a cube that will change the color of the ball to, say, green when it touches it. Take the color change code from the end of the tutorial and make sure the cube doesn’t accidentally color the floor too!

  2. In the second scene, take the camera out of the character in the hierarchy, replicate them on the scene, and completely rewrite their script so they run in random directions. And then create a script for the fire zone in which to implement everything that we did in this lesson.

    Now you have a bunch of unfinished minions running around the map, each of which grows and flickers when it enters the fire zone!

That’s all!

PS This is my first article. I will be glad to see comments with constructive criticism. Also ready to answer questions in the comments.

PPS Does anyone know where people usually put links like I have here – to the game folder? And then on Google drive you don’t really want to take up space, and online file hosting services allow you to arrange files only for a specific period …

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *