Home > Enterprise >  OnTriggerStay() stops working if any other objects triggers OnTriggerExit() method
OnTriggerStay() stops working if any other objects triggers OnTriggerExit() method

Time:06-23

I am working on a puzzle game, I have a grid that player places the pieces on it. The grid tiles have 4 sensors(child objects) that have BoxCollider2D to check if the tile is covered by a puzzle pieces.

When I place a piece on a tile, the Sensors detects it with OnTriggerStay2D() and when i move the piece away from the tile, Sensors detect it with OnTriggerExit2d(). it works without a problem until now. But while a tile has a piece on it and the Sensors says it is covered with a piece if I moved an other piece above the tile it triggers OnTriggerExit2d() and Sensors' bool variable becomes false. Even if there is still a piece on the tile, OnTriggerStay2D() stops working. Doesn't it checks if there are a collision in every frame.

This is the code of the sensors.

public class GridTileSensor : MonoBehaviour
{
    public bool isCovered;
    void Start()
    {
        isCovered = false;
    }


    private void OnTriggerStay2D(Collider2D collision)
    {
        if (collision.gameObject.CompareTag("PuzzlePiece") == true)
        {
            if (collision.gameObject.GetComponent<Dragger>().isPlaced == true)
            {
                isCovered = true;
            }
        }
    }

    private void OnTriggerExit2D(Collider2D collision)
    {
        if (collision.gameObject.CompareTag("PuzzlePiece") == true)
        {
            isCovered = false;
        }
    }
}

CodePudding user response:

You are trying to handle interaction with several objects with the single bool variable. It is not possible. You need to modify your code to be able to handle multiple objects.

Simple logic:

  • store puzzle pieces that are covered by your sensor in the list;
  • add a puzzle piece to the list when collision begins (perhaps, it is better to use OnTriggerEnter2D instead of OnCollisionStay2D but it needs to be tested)
  • remove a puzzle piece from the list when the collision ends
  • your isCovered property will be true in case of there is at least one puzzle piece in the list

Something like this, but you can modify whatever you want to:

public class GridTileSensor : MonoBehaviour
{
    private List<Collider2D> _activeCollisions = new List<Collider2D>();
    
    public bool IsCovered
    {
        get { return _activeCollisions.Count > 0; } 
    }
    
    private void OnTriggerStay2D(Collider2D collision)
    {
        if (collision.gameObject.CompareTag("PuzzlePiece") == true)
        {
            if (collision.gameObject.GetComponent<Dragger>().isPlaced == true)
            {
                if(_activeCollisions.Contains(collision) == false) // we are using OnCollisionStay2D here, so need to be care about adding the same object several times
                {
                    _activeCollisions.Add(collision);
                }
            }
        }
    }

    private void OnTriggerExit2D(Collider2D collision)
    {
        if (collision.gameObject.CompareTag("PuzzlePiece") == true)
        {
            Debug.Assert(_activeCollisions.Contains(collision)); // just to be sure that it is "legal" event for the already handled object 
            _activeCollisions.Remove(collision);
        }
    }
}
  • Related