Unity 2D Course Lesson 28 issues

Hi,

I am having some trouble with the topic mentioned above.

I was following along fine. I have this code in Driver.cs:

void OnTriggerEnter2D(Collider2D collision)

{

    if (collision.CompareTag("Boost"))

    {

        currentSpeed = boostSpeed;

        boostText.gameObject.SetActive(true); 

        Destroy(collision.gameObject);

    }

    

}



void OncollisionEnter2D(Collider2D collision)

{

    Debug.Log("Speed reduced");

    if (collision.CompareTag("WorldCollision"))

    {

        currentSpeed = regularSpeed;

        boostText.gameObject.SetActive(false);    

    }

Initially, I had an issue of oncollisionEnter2D never being called. Then I realized that I used a small c instead of capital c. So, I changed to OnCollisionEnter2D, but now when I try to run it, I get these error messages:

Script error: OnCollisionEnter2D
This message parameter has to be of type: Collision2D
The message will be ignored.

I get two of the same messages. Now, it won’t eve run. If I switch back to small c, it will run, but it never detects collision.

Could you please help me fix this?

Best regards,

Sang-Woo

1 Like

Hi Sang-woo,

Welcome to our community! :slight_smile:

C# is case-sensitive. If methods do not get executed, the first thing I would do is to check the spelling. The correct spelling is OnCollisionEnter2D.

The error message states that the type of the parameter of the OnCollisionEnter2D must be Collision2D. If you take a look at your code, you’ll see void OnCollisionEnter2D (Collider2D collision) { }. The type inside the parentheses must be Collision2D, not Collider2D. The spelling is very similar, so this details might be difficult to see. Please fix this, then save your script, and test your game.

Does your game work now? :slight_smile:

1 Like

Thank you so much, Nina. I have fixed it as per your suggestion. So, the code looks like this:

void OnCollisionEnter2D(Collision2D collision)

{

    Debug.Log("Speed reduced");

    if (collision.CompareTag("WorldCollision"))

    {

        currentSpeed = regularSpeed;

        boostText.gameObject.SetActive(false);    

    }

    

    

}

But, now, I get the following error:

Assets\Scripts\Driver.cs(65,23): error CS1061: ‘Collision2D’ does not contain a definition for ‘CompareTag’ and no accessible extension method ‘CompareTag’ accepting a first argument of type ‘Collision2D’ could be found (are you missing a using directive or an assembly reference?)

I believe I was following along what was being done to clean up in lesson 29. So, for Collision2D, how do I compare tags?

Thanks in advance.

Sang-Woo

Never mind.

I figured it out. I went back to the lecture ans saw that I needed collision.collider.CompareTag()

I figured it would be better if I can figure it out on my own in the long run.

Thank you for your help, anyway.

Best regards,

Sang-Woo

Sometimes, Unity can be fairly confusing. :confused:

I’m telling you how to figure out what we can access via code. This will hopefully help you with similar problems in the future.

The error message states that the Collision2D class does not contain any definition for CompareTag(). If you double click the error message, the line with collision.CompareTag will get highlighted in your code.

To figure out what we are able to access, we usually take a look at the Unity API.

In this case, we look for Collision2D. Given the docs are correct, there is no CompareTag() method but there are other things we could access via collision.{member} where {member} is just a placeholder, not real code.

Let’s ignore the code for a moment. What do we want to achieve? We want to know if the other game object has got the “WorldCollision” tag.

With this in mind, let’s take another look at the API. In the list, we can see many things we could access. We skim the description and click whatever sounds promising. This is more or less guessing around. (Sometimes, there is no premade solution, so our search might end in an impasse. In this case, there is a solution, though.)

If you want to challenge yourself, please stop reading, and check the API yourself.

How I looked for the relevant information, and found it …

I’m checking gameObject first, and get to this page. Then I click the type GameObject. I can see that the GameObject class (and therefore the object) contains a CompareTag() method. Perfect.

Now, I know what I need. I just have to follow the “path”: Collision2D object → gameObject → CompareTag().

In your case, the variable of type Collision2D is named collision, so we write collision.gameObject.CompareTag.

In your code, you would write if (collision.gameObject.CompareTag("WorldCollision")).

That will hopefully work. If not, I made a mistake somewhere.


As a side note, Collision2D and Collider2D are fairly inconsistent. I have no clue why one class contains CompareTag() while the other doesn’t. Both classes are written by humans, though. Some classes were created decades ago. For this reason, I wouldn’t worry too much about it. Instead, I would briefly check the API to hopefully get a solution. Everything else is just a waste of time. ^^

I suppose it has to do with the fact that Collider2D - something that can collide - is a kind of Behaviour and thus inherits the CompareTag method from the Behaviour class, whereas Collision2D acts as a data container about a collision that occurred. Thus a Collision2D is not part of a Game Object, but tags are assigned to Game Objects. :thinking:

But I agree that they could have added such a method to the class nevertheless, considering that some of its other members are also redundant to each other and seem to provide convenience to write shorter code.

1 Like

Yes, that’s what I thought was the reasoning behind Collider2D and Collision2D.

I’m just wondering why OnCollision*() takes in a “collider” whereas OnTrigger*() takes in an “event”. Unless I’m missing something obvious, Collision2D would have worked for both methods because we could easily access the colliders via the Collision2D object: collider and otherCollider.

Furthermore, frameworks usually provide solutions for common problems. The reason we use OnCollision*() or OnTrigger*() is to check if the game objects involved in our collision/trigger event meet our condition(s). In our case, we check a tag. In other cases, we might look for a component. Why is getting the relevant information in OnTrigger*() more difficult than in OnCollision*()? That’s a rhetorical question. :confused:

1 Like

Thank you all for you thoughts. I had a related question.

As I was following along on the Lesson 47, I had this code for crash detection:

void OnTriggerEnter2D(Collider2D collision)

{

    int layerIndex = LayerMask.NameToLayer("Floor");



    if (collision.gameObject.layer == layerIndex) 

    {

        crashParticles.Play();

        pController.DisableControls();

        Invoke("ReloadScene", delayFactor);

    }

}

For the challengeregarding displaying the snow particles, I used the same code as above to detect that the board was touching the floor, but the above never got called, and the right answer was the followng:

void OnCollisionEnter2D(Collision2D collision)

{

    int layerIndex = LayerMask.NameToLayer("Floor");



    if (collision.gameObject.layer == layerIndex) 

    {

        snowParticles.Play();



    }

}

So, why does OnTriggerEnter2D never get called in this scenario, and what is the exact difference beterrn OnTriggerEnter2D and OnCollisionEnter2D? Could you please explain this?

Best regards,

Sang-Woo

In Unity’s physics simulation, we have two types of collisions: non-trigger and trigger.

  • A non-trigger collider has got a “solid” body.
  • If two “solid” bodies collide, they could, for example, bounce off.
  • A trigger collider has got a “ghost” body.
  • If a “solid” body collides with a “ghost”, or if two “ghosts” collide, nothing happens in regards to the physics.

The physics simulation is a resource-intensive calculation. The less it has to calculate, the more performant is our game. Trigger colliders are the most performant colliders because Unity won’t have to calculate how something bounces off.

To increase the performance, Unity also distinguishs between “moveable”(= dynamic, kinematic) and “non-moveable” (= static) colliders. We can define this in the Rigidbody2D component. If we move a static collider, this will have a negative impact on the performance.

Is this clear so far?


If so, on to the tricky part: the events. Certain events get rised only if certain conditions are met. There are two relevant properties: collider and moveable (and their respective counterpart).

I don’t know the conditions for the events by heart, so I usually take a look at this table in the manual.

With this table, you could check your game to see if you have all the relevant things and settings for OnTrigger*(). If your game objects do not have any trigger collider attached, that could explain why the method wasn’t called.

Furthermore, the OnTriggerEnter2D() method gets called only if a collider enters another collider. If your game object is inside another collider, this method won’t get called either.


In 2D games, you would use Collider2D instead of Collider. And you would use, for example, OnCollisionEnter2D() instead of OnCollisionEnter(). The rest works the same, which is why I linked the “3D” docs.

In your 2D game, make sure not to use the wrong collider types.


Last but not least, please add Debug.Logs to your code to see if the methods get called. Do not rely on what you see in Unity because code gets executed within milliseconds. Your code might work perfectly fine.