Been googling for hours trying to figure this out. I’m using 2D physics. I want to set up a “filter” for a specific rigidbody so that it collides with specific Layers.
The collision matrix does not have enough flexibility with only 32 layers. For instance, status effects on characters can require them to only collide with specific Layers temporarily (“unitwalking”, or passing through a wall, etc). I cant simply make a unique Layer and switch to it because I will run out of Layers with all of the specific cases.
I used Box2D in past projects, and when creating a Body you can make a custom filter to decide what it collides with, like this: Collision filtering - Box2D tutorials - iforce2d. Is this not possible with unity’s 2D physics?
The only options outside of the collision matrix that I see are Physics.IgnoreLayerCollision (which sounds like its the same thing as the collision matrix) and Physics.IgnoreCollision which would be ridiculous to use for something like this (having to keep track of every Body that I don’t want it to collide with).
Box2D also has the option to analyze a collision and cancel the collision in a callback. That also doesn’t seem to exist in Unity? Whats the deal?
Edit: Just wanted to mention that I tried using Physics.IgnoreCollision() inside of OnCollisionEnter2D() - it prevents later collisions from happening between the two bodies but doesn’t prevent or cancel the one that caused OnCollisionEnter2D() to get called
You could use OnTriggerEnter2D and test a certain logic that will then turn a collider on a child on or off depending on what you’re trying to do, this way you can use tags which I think are unlimited? You might also be able to use the platformeffector2D and manipulate the collider mask? In my project I ran into the limits of the 32 layer collision matrix and had to resort to workarounds in code which weren’t as elegant but ultimately worked.
Thanks, that could be a workaround for certain cases for sure. Placing a larger trigger-collider around a smaller physics-simulated collider would let you use onTriggerEnter2D to decide whether or not Physics.IgnoreCollision() should be set on the smaller physics-simulated collider for the incoming collider.
But all of these things are such a hassle to do and waste CPU (doubling the number of colliders, etc), and are straying from the true physics simulation (enabling/disabling colliders, calling Physics.IgnoreCollision() mid-simulation, etc).
As far as I see it there is no reason not to be able to set a collision filter for a rigidbody besides it being more complex than the “collision matrix”. Pretty annoyed that functionality is being traded off for simplicity
It’s not a trade off for simplicity at all. It’s that you don’t have access to the native C++ side and plugging in a marshalled C# call just isn’t going to happen. Not only would it be super slow, it’d allow you to cause chaos because this is called during the simulation loop (contact creation/update) and you’d be allowed to use any of the Unity API meaning you can do structural changes and we couldn’t protect you from a crash.
It’s not clear however if you were suggesting applying a collision matrix per-body however as that would be possible to implement without side-effects or performance issues.
Honestly I see no reason to use physics in a 2D project. You should just create your own and iterating over them to check if they overlap using x,y,width,height. It might be more work but performance gains alone make it worth it.
Having used Box2D on a previous project, I’m well aware of how dangerous it can be to do things mid-simulation update (haha). That being said, I did use the mid-simulation callbacks successfully for a number of things, namely the option to cancel a collision. I’ll admit I don’t know how slow it was to do that, but the physics-world-update didn’t take enough CPU time to worry about it. I do agree that a lot of users would probably screw things up and cause all sorts of crashes if given the mid-simulation callback.
For me personally, the mid-sim callbacks aren’t totally necessary, but the fact that I can’t set the collision filter/matrix per-body AND don’t have the option to scrutinize and cancel a collision with the mid-sim callback puts me into a position where I’m going to run out of “physics layers”. I have too many objects that require specific collision filtering. Like I mentioned above, characters changing what they collide with in-game from abilities/powerups each have to have their own Layer. Items on the ground that collide with the player to get picked up, need to collide with boundaries, but shouldn’t collide with enemies. Debris pieces that the player can kick around. Etc.
Yes, that would would be extremely helpful - if given that option I believe I’d be able to make a straightforward solution to all of my issues!
I have a unique situation that I’m trying to figure out the best way to handle @MelvMay
Lets say I have 100 balls (ballA, ballB, ballC… ) with circle colliders, and 100 triangles (triangleA, triangleB, triangleC…) with triangle polygon colliders. I want ballA and triangleA to only collide with eachother, and absolutely nothing else. Same with ballB and triangleB, etc. None of them are triggers, I want them to simulate physics (note, this isn’t just a hypothetical case, but its easiest to explain with the balls/triangles)
How could I set that up? These are the two ways I can think of:
Add a trigger collider to each of the balls that extends way out past its ball-collider, and use OnTriggerEnter2D to scrutinize the incoming collider and set IgnoreCollision() as needed (for everything except the corresponding triangle-collider). I think this would work alright. The two downsides/gotchas being that it requires another collider for every ball/triangle pair, and it requires the outer trigger-collider to be big enough that it collides with the incoming collider at least one frame before reaching the ball-collider. So the faster the ball/triangle are moving the bigger the outer trigger-collider has to be.
Manually keep track of all colliders that are using the Physics Layer that the balls/triangles are using, and every time you spawn a ball/triangle pair set their IgnoreCollision() for other existing things on that Physics Layer, and update all pre-existing balls/triangles to also not collide with the new ones. I don’t really like this option, it doesn’t seem practical.
You can’t use IgnoreCollision on a contact callback because the contact has already happened. The callback isn’t pre-contact, it’s after the fact.
There is no way to allow only two specific colliders to contact and no others apart from using queries to determine contacts and discarding stuff you’re not interested in. Even that won’t scale well depending on how it’s done.
That sounds similar to what I was suggesting with option #1 - essentially each special-case collider testing for “whats near me”, and deciding if it should preemptively call IgnoreCollision() for them.
Not really. Usnig queries to hope to detect a contact before it might happen then call ignore collision isn’t going to be reliable. I simply meant add colliders that are set to not contact anything and use queries exclusively to determine collisions. Of course I have no idea on what you’re doing and what kind of collision response you want. In the end, if you want full and correct collision response then this is going to prove difficult.