I’m wondering if I’m doing anything wrong. I’m trying to check for overlaps against 2D trigger colliders by using a Physics2D.OverlapBox with a ContactFilter set to useTriggers.
using System.Collections.Generic;
using UnityEngine;
public class Test : MonoBehaviour {
private static List<Collider2D> colliders = new List<Collider2D>();
void Update() {
var contactFilter2D = new ContactFilter2D {
useTriggers = true
};
var count = Physics2D.OverlapBox(Vector2.zero, Vector2.one, 0f, contactFilter2D, colliders);
Debug.Log(count);
}
}
The count is 0, meaning that the collider is not hit. If I set the collider to not be a trigger, the overlap hits.
It seems like turning off Queries Hit Triggers in the project settings means that the useTriggers parameter of the ContactFilter doesn’t do anything. If Queries Hit Triggers is on, then the trigger collider is found if useTriggers is true and not found if it’s false, as expected.
Is this a bug? I assumed that using the contact filter and asking for triggers would override the global settings.
In 3D physics, we do things like this with QueryTriggerInteraction, in order to override the global settings. Is there any way to override the global settings in 2D physics?
It’s not a bug and 2D physics had this implemented before the QueryTriggerInteraction in 3D physics.
That said, I can see the value of allowing the ContactFilter to override the global setting so that’s an oversight. The problem now is that changing that would break existing projects. All filtering checks if it’s a trigger and will ignore it if the global trigger option is off OR the contact filter trigger option is off). You’re saying ignore them if both the global AND the contact filter are off.
The only way to change that now would be to change the global to be an enum option that allows it to force this on/off or simply default it it on/off with it overridable in the contact filter.
A simpler method would be to change the ContactFilter2D so that it can override the global which would mean a similar thing but be located in the filter itself.
Unfortuntately neither of the above could be backported (we cannot backport features, property changes etc) so would at best be part of 2021.2 onwards.
BTW: If you turn on the “Queries Hit Triggers” global option then you can turn that off with the ContactFilter2D (just not the other way around). Also, you can use “ContactFilter2D.NoFilter()” to use it with no fitlering which includes triggers allowed.
Thanks for the replies!
We don’t want to use the “hit triggers by default” solution, since almost no raycasts wants to hit triggers, and by experience it causes hard to track down bugs when we have the option on (at least it did in 3D before the option existed!)
My current workaround is:
var old = Physics2D.queriesHitTriggers;
Physics2D.queriesHitTriggers = true;
// raycast with ContactFilter
Physics2D.queriesHitTriggers = old;
But, yes, the solution in 3D physics is a lot better, so doing that would be an improvement. Obsoleting ContactFilter2D.useTriggers and replacing it with a triggerInteraction enum would be something the auto-updater would handle, no?
Related, the Physics2D casts API is a bit of a mess. For example, you have OverlapBox, OverlapBoxAll, and OverlapBoxNonAlloc. That’s fine, except that the non alloc versions with the ContactFilter is in OverlapBox. So that’s both inconsistent with 3D, and also makes finding the good methods that you should use hard to find.
It kinda feels like somebody started refactoring the API, but just gave up halfway through. I assume the mess is due to backwards compatibility? Unity’s made some choices around backwards compatibility that it feel like just causes everything to be a little bit bad forever, in order to avoid a tiny cost when upgrading.
Not something you can do anything about, but I have no idea who calls those kinds of shots
Yes that would work but features are not allowed to be backported. Only bug fixes.
Actually you have that the wrong way around. 3D physics never got around to fixing the query API so all those “All” & “NonAlloc” (which originally was copied from the 2D equivalent) are still the only way to get multiple results and don’t support List as 2D does. I know it’s always seen as 2D catching up to 3D but this simply isn’t true.
For 2D, all the “All” and “NonAlloc” are tentatively deprecated and if you remove that suffix you’ll see overloads for single, multiple of array and list so you use “OverlapBox” for all box overlaps (nothing else) and the same with ALL the 2D physics queries which all support List".
The reason those were not marked as deprecated was that it was feared it would cause chaos with users complaining about the console warnings. Personally, I’d do that but it’s a sore topic.
In short, in 2D you don’t have silly “All” or “NonAlloc”.
I wasn’t suggesting it for backports, but for the future! I totally agree that you shouldn’t remove things from the API in LTS or Tech, that’d be a disaster.
When I become dictator of the world, I’ll appoint you head of deprecating stuff at Unity!
By the way, this popped up in a discussion at work today, and I noticed that this is in no way noted in the documentation. ContactFilter2D’s docs for example makes no mention that “useTriggers” does nothing if the global setting is false.
There’s also a big annoyance with the current API that, at least as far as I can tell, there’s no way to do a raycast that just returns a single RaycastHit2D when using the ContactFilter. So we have to allocate or store a list somewhere and check that hits.Count < 0 in order to interact with use/dontuse triggers.