Triggering only 1 collider on a gameobject with multiple colliders in Unity2D

Viewed 383

enter image description here enter image description here

In my example I have a character with 2 colliders on it. Capsule collider and box collider. Also, I have a heart gameobject with its own script as shown below.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class HeartCollectable : MonoBehaviour
{
    private void OnTriggerEnter2D(Collider2D collision)
    {
            if (Player.playerHealth < Player.numberOfPlayerHeart)
            {
                Player.playerHealth += 1;
                Destroy(gameObject);
            }
    }
}

My problem is, when I jump and land on this game object. My capsule and box collider trigger simultaneously. That way player gain 2 health instead of 1. How can I trigger only one of them ?

4 Answers

Here is my solution about this problem. In the OnTriggerEnter2D() we can check the type of the collision with GetType() function. If it is a capsule collider its type will be "UnityEngine.CapsuleCollider2D". If it is a box collider it will be "UnityEngine.BoxCollider2D". Then we can convert this type into a string and check whether it is a box or capsule collider. Like this way;

private void OnTriggerEnter2D(Collider2D collision)
    {
        if (collision.GetType().ToString().Equals("UnityEngine.CapsuleCollider2D"))
        {
            if (PlayerMovement.playerHealth < PlayerMovement.numberOfPlayerHeart)
            {
                PlayerMovement.playerHealth += 1;
                Destroy(gameObject);
            }
        }
    }

I don't know is it the best solution but it is work for me.

There are a lot of ways of doing this. here's the simplest I can think of:

    using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class HeartCollectable : MonoBehaviour
{
   private bool hasBeenCollected = false;

    private void OnTriggerEnter2D(Collider2D collision)
    {
            if (!hasBeenCollected && Player.playerHealth < Player.numberOfPlayerHeart)
            {
                hasBeenCollected = true;
                Player.playerHealth += 1;
                Destroy(gameObject);
            }
    }
}

basically just add a bool you set immediatly after collecting to make sure you don't collect twice.

If your game gets more complex I would suggest making a collider on the player that only collides with powerups using layers and the Layer Collision Matrix. That way only 1 collider ever collides and you can tweak the collection radius but again I don't think you need anything more complicated for now.

The cleanest solution would be to use seperate Physics Layers.

You want to set your heart on it's own layer and have that layer only interact with your main player collider, or put your feet one their own layer which does not interact with the heart.

You can access all these settings in Edit > Project Settings > Physics.

Layer collision matrix

By unticking an option you can disable physics interactions (including trigger collision detection) entierly between two layers.

This will make your heart ignore the other collider and will only trigger the OnTriggerEnter2D once.

You can try the following code and debug it to see if you can get 1 HP

enter image description here

Related