how to distinguish which layer has been detected with OnTriggerEnter2D first?

Hey All,

I am trying to use layermasks with void OnTriggerEnter2D

Currently, in my Game, I will have 3 gameObjects sitting stacked on top of each other:

  • GO1: BigResource
  • GO2: SmallResource
  • GO3: Plot

Each game object has a layer allocated to them based on the naming above.

Using a boxCollider2D and OnTriggerEnter2D, I want to detect the following:

If GO1: BigResouce exists first if it does, I don’t want to collider to detect the other 2 GO underneath it.

If GO1: BigResouce does not exist, then the boxCollider2D and OnTriggerEnter2D should detect GO2: Small Resource.

If GO2: BigResouce does not exist, then the boxCollider2D and OnTriggerEnter2D should detect GO3: Plot.

Else Do nothing

Below is my code:

private void OnTriggerEnter2D(Collider2D collision)
    {
        if (collision.CompareTag("Player"))
        {
            if (collision.gameObject.layer == LayerMask.NameToLayer("BigResource"))
            {
                Debug.Log("Hit a Big Resource");
            }
            else if (collision.gameObject.layer == LayerMask.NameToLayer("SmallResource"))
            {
                Debug.Log("Hit a Small Resource");
            }
            else if (collision.gameObject.layer == LayerMask.NameToLayer("Plot"))
            {
                Debug.Log("Hit a plot");
            }
        }
    }

Are you able to advise what I am doing wrong?

Thank you

MegaTDog

(Anthony)

Note: I was using a raycast before to do this, which was working however I decided I didn’t want to use a raycast anymore due to the way I want this system to work. My system needs to beable to detect multiple game objects in a 1x1 grid, 1x2 grid, 2x2 grid, 2x3 grid and 3x3 grid. Using raycast i couldn’t see how to achieve this since a raycast only returns the first object it hits but using BoxColliders I can, by instantiating extra BoxColiders in the required grid layout.Below is my raycast code, just in case it is possible to achieve this gird layout required with Raycast

void playerRaycast()
{
    // See: https://docs.unity3d.com/ScriptReference/Physics2D.Raycast.html & https://answers.unity.com/questions/1499447/how-to-distinguish-which-layer-has-been-hit-by-ray.html
    requiredLayersMask = layermask1 | layermask2 | layermask3; //Logic copied from here: https://answers.unity.com/questions/1499447/how-to-distinguish-which-layer-has-been-hit-by-ray.html
    //int layerMask = LayerMask.GetMask("Plot"); // Use whatever mask you assigned to your ground tiles (plots) (Not used, but could be useful code)

    float distance = 1.0f; //Changes this to make the raycast go further?
    Vector2 direction = this.playerDirection == PlayerDirection.Left ? Vector2.left :
                        this.playerDirection == PlayerDirection.Right ? Vector2.right :
                        this.playerDirection == PlayerDirection.Up ? Vector2.up : Vector2.down;
    RaycastHit2D hit = Physics2D.Raycast(transform.position, direction, distance, requiredLayersMask);

    Debug.Log("Player is facing: " + playerDirection);

    Debug.DrawRay(transform.position, direction, Color.red, 10, false);
    Debug.Log("Raycast: " + hit.transform);

    //If the raycast collider hits another collider, Do something such as farm work or talk to a NPC
    if (hit.collider != null)
    {

        if (hit.collider.gameObject.layer == LayerMask.NameToLayer("BigResource"))
        {
            Debug.Log("Hit a Big Resource");

            if(hit.collider.tag == "rock")
            {
                hit.transform.gameObject.GetComponent<BigRockScript>().DamageObject(hit);
            }
            else if(hit.collider.tag == "log")
            {
                hit.transform.gameObject.GetComponent<BigLogScript>().DamageObject(hit);
            }
        }
        else if (hit.collider.gameObject.layer == LayerMask.NameToLayer("SmallResource"))
        {
            Debug.Log("Hit a Small Resource");

            if (hit.collider.tag == "rock")
            {
                hit.transform.gameObject.GetComponent<SmallRockScript>().DamageObject(hit);
            }
            else if (hit.collider.tag == "log")
            {
                hit.transform.gameObject.GetComponent<SmallLogScript>().DamageObject(hit);
            }
        }
        else if (hit.collider.gameObject.layer == LayerMask.NameToLayer("Plot"))
        {
            cropManagerController = hit.transform.gameObject.GetComponent<CropManagerController>(); //This completes the reference to the CropManagerController when the raycast hits a gameObject that is CropManagerController
            cropManagerController.DoFarmWork(hit); //Depending on the state of the plot, this could be watering, planting a seed, cleaning rubbish etc }
        }
    }
}

ok… first of all never use “else if” they very slow and sometimes they are not detected.
So you can try change all the “else if” to “if”.

Also, the layers are very irritating because there are two list of layer that might cause troubles…
one are the serialized fields or public layer mask variables that you made and the other one is the list where you choose the layer of each object, if you are a beginner I recommend you to use Tags.

But if I were in your situation… You could adapt this to what ever you want.

    void OnCollisionEnter2D(Collision2D collision)
    {
        Debug.Log($"Hit a {LayerMask.LayerToName(collision.gameObject.layer)}");
    }

Hope I’m right and you like it.