Check for Lack of Collisions

Ok, here’s a tough one. For me at least, as this has bee keeping me from going to sleep for a good while now. I have a box collider trigger with a bool that is supposed to return true when it is colliding with anything at all, and false only when it is colliding with nothing. Like, when all objects intersecting with it have been knocked away by player.

I have the bool set to true by default, and I’m using OnTriggerStay() to see if the trigger collision is maintained. If I set the bool to false in OnTriggerExit() than it goes false if any one object exits the trigger, which is too soon for my purposes. How do I tell my bool to return false once no objects are inside the trigger, and not before?

There are many ways to accomplish things like this, but this code will accomplish what you are after most closely aligned with your original approach:

using UnityEngine;
using System.Collections;
public class TriggerCheck : MonoBehaviour {
	public bool Occuplied = false;  // This is what you query
	bool SomethingInsideCheck = false;
	void Update () {
	
	}
	void OnTriggerStay(Collider c)
	{
		SomethingInsideCheck = true;
	}
	void LateUpdate()
	{
		Occuplied = SomethingInsideCheck;
		SomethingInsideCheck = false;
	}
}

The public bool “Occupied” keeps track of if any other collider as within the trigger the previous frame.

You may want to know the state on the current frame. In which case make the “SomethingInsideCheck” public and check that. It makes the “Occupied” bool redundant, but but is useful in the Inspector if you want to see a checkbox go checked/unchecked live. The SomethingInsideCheck will always appear false/unchecked in the Inspector using this approach due to order in which things execute/update in Unity. But checking it in various Update methods will be accurate since triggers happen before Update calls.

I may have solved my own problem with a workaround, and I’m posting it in case this issue comes up for anyone else. I’m still open for better solutions if anyone has any. Here’s what I did:

bool colliding = true;
bool isBeingExited;

void OnTriggerStay(Collider collider)
{
     isBeingExited = false;
}
void OnTriggerExit(Collider collider)
{
     exited = true;
     StartCoroutine(ConfirmEmpty());
}
IEnumerator ConfirmEmpty()
{
     yield return new WaitForSeconds(2);
     if(isBeingExited)
          colliding = false;
}

This way, every time an object exits the trigger, isBeingExited is set to true. If other objects are still intersecting the trigger, OnTriggerExit sets the value back to false. The coroutine assures me that for 2 seconds after the last exit event, no other intersections are being detected. Only then is colliding set to false.