Physics2D CircleCast returns nothing when using a contactfilter

I know what you’re thinking - the contact filter isn’t set up right. :wink: However, I’m getting unusual results in that I can get results from one particular call, using NoFilter()…

	int hitCount = Physics2D.CircleCast(pos, radius, facing, contactFilter.NoFilter(), rayHits, 1.2f);

The above works. However, if I populate contactFilter with anything, no colliders are detected. If I use

	contactFilter = contactFilter.NoFilter();

and pass contactFilter, nothing is detected. If I set contactFilter to the defaults defined in the manual for ContactFilter2D.NoFilter()

	contactFilter = new ContactFilter2D();
	contactFilter.layerMask = Physics2D.AllLayers;
	contactFilter.useTriggers = true;
	contactFilter.minDepth = -Mathf.Infinity;
	contactFilter.maxDepth = Mathf.Infinity;
	contactFilter.minNormalAngle = -Mathf.Infinity;
	contactFilter.maxNormalAngle = Mathf.Infinity;

I’ve tried positive and negative values for ‘min’ parameters.

My colliders are all kinematic triggers.

Why does passing conactFilter.Nofilter() work but no variation of contactFilter work?

Edit: Raycast works with my contact filter, although it won’t detect my TileMap composite collider which is what I am needing the circle cast for.

There’s nothing special about it, it’s all C# and you can find it here: UnityCsReference/Modules/Physics2D/ScriptBindings/Physics2D.bindings.cs at 611307378c56a1b2f90eb1018332166cbe3c9c03 · Unity-Technologies/UnityCsReference · GitHub

You are setting things like depth/normal-angle/layer-mask but it’ll only use those those if you activate the option with the appropriate flags.

Normal angles don’t use infinity btw. It’s best to just turn-off thing things you’re not interested in rather than just setting large ranges and including them; it also reduces the work it has to do.

Note that it detecting things or not isn’t relevant to what type of Unity collider you’re using. The physics engine at this level knows nothing about such high-level concepts. There’s only primitive circle, capsule, edge and 8-sided polygons.

Those are just examples of the many parameters I’ve tried, from ‘nothing’ to ‘everything’. My intended code was:


contactFilter = new ContactFilter2D();
contactFilter.layerMask = Physics2D.AllLayers; // Add layer mask here

This works with RayCast() but not CircleCast()

If I use all the values you linked to here, nothing is detected. If I pass a new contact filter without changing the default values, it does not work. Only if I directly use contactFilter.NoFilter() as a parameter does it work in the CircleCast.

Edit: Ray and Circle casts are working fine in a different test project on the same unity version. They aren’t working in a test scene in my game.

Using a test script where I create a contact filter, two sprites with RBs and circle colliders. I draw a ray and cross and change colour based on number of contacts detected.

	private void Start() {
		rayhits = new RaycastHit2D[20];
		conFilter = new ContactFilter2D();
		colHits = new Collider2D[20];
		col_obj1 = go_obj1.GetComponent<Collider2D>();
	}

	private void FixedUpdate() {
		Vector2 dir = new Vector2(1, -1);
		dir.Normalize();
		float dist = 2;
		int colCount = Physics2D.Raycast(go_obj1.position, dir, conFilter, rayhits, dist);
		// int colCount = Physics2D.CircleCast(go_obj1.position, 1, dir, conFilter, rayhits, dist);
		Color c = Color.black;
		if (colCount >= 1) {
			c = Color.red;
		}
		Debug.DrawRay(go_obj1.position, dir * dist, c);

		colCount = col_obj1.OverlapCollider(conFilter, colHits);
		c = Color.blue;
		if (colCount >= 1) {
			c = Color.green;
		}
		Utilities.DrawCross(go_obj1.position, c, 0.1f);
	}

This code works in a different project on the same Unity version, but not in my game. however, if I replace ‘confilter’ with ‘confliter.NoFilter()’ in the cast calls, the objects are detected.

Not sure what’s going on there.

Without seeing it and being able to reproduce it I cannot suggest anything else. If you have a simple reproduction case I could look at it’d help.

I was editing as you replied. It works fine in a different project but not in my game.

Yes I saw but that doesn’t enable me to know what’s going on though. :wink:

I’ve managed to create a repro by removing everything from my game except the test scene:

PhysicsDebug.zip (72.3 KB)

Open Scenes / Blank. There’s two squares. Test script is attached to the camera. Run it and move the green (turns blue) square around in the editor and it and the drawn ray change colour based on collisions with the orange square. Change the confilter.NoFilter() to just confilter and it does not change colour.

In this test, setting confilter = confilter.NoFilter() sees it work in the ray tests. That doesn’t work in my game though.

Doesn’t work in game or test:

ContactFilter2D conFilter = new ContactFilter();
int colCount = Physics2D.Raycast(go_obj1.position, dir, conFilter, rayhits, dist);

Does work in game and test:

ContactFilter2D conFilter = new ContactFilter();
int colCount = Physics2D.Raycast(go_obj1.position, dir, conFilter.NoFilter(), rayhits, dist);

Doesn’t work in game but does work in test:

ContactFilter2D conFilter = new ContactFilter();
conFilter = conFilter.NoFilter();
int colCount = Physics2D.Raycast(go_obj1.position, dir, conFilter, rayhits, dist);

Works in both:

ContactFilter2D conFilter = new ContactFilter();
ContactTilter2D testFilter = conFilter.NoFilter();
int colCount = Physics2D.Raycast(go_obj1.position, dir, testFilter , rayhits, dist);

Edit: Lastly, CircleCastNonAlloc etc. works, so currently looks like a weird ContactFilter issue.

You’re asking why it doesn’t work when you use “conFilter = new ContactFilter2D()” on its own and as I said above, if you do that then everything is at default including “useTriggers” which will be false so it doesn’t detect your triggers.

If you look again the source for NoFilter you can see it sets it to true: UnityCsReference/Modules/Physics2D/ScriptBindings/Physics2D.bindings.cs at 611307378c56a1b2f90eb1018332166cbe3c9c03 · Unity-Technologies/UnityCsReference · GitHub

If I set this to true then it works perfectly fine using either.

Aaarrrgh!

So I had that first in my game. The first time I added the contact filter, I added UseTriggers and nothing else. It wasn’t working which led me to all this. Clearly in creating the repro something happened because yes, UseTriggers works in the repro but not in my game.

Ahhh.

ContactFilter is initialised without needing = new ContactFilter(). It’s a struct.

Turns out I’m not calling my Initialisation method, so wasn’t setting the contact filter parameters. :speak_no_evil: My assumption was if it wasn’t calling new ContactFilter() I’d have had a ‘null’ error, but of course CF is a struct.

Doh! Thanks for your time on this silly mistake.

1 Like

It’s okay, we all make them each and every day! As long as you’re moving forward now. Good luck with what it is you’re doing.

And to add, I made a mistake when I wanted consistency so I added it as “useTriggers” rather than “ignoreTriggers”. If it were that then it’d default to false and not ignore triggers i.e. it’d be “no filter” by default. We all live and learn.

Also in later Unity versions, “NoFilter” is a Static method as it should’ve been in the first place. Yep, another mistake. :slight_smile: