Most efficient (and effective) way to get which side occurred for a collision...

In Unity the two major types of collision event methods are OnTriggerEnter2D(Collider2D target) and OnCollisionEnter2D(Collision2D col). The former is for triggers, which are convenient in that they allow an object to be passed through by other objects but still invoke a script. The latter is for regular physics objects. When OnCollisionEnter2D is called for these, the Collision2D structure allows access to the contact point and hence a very efficient check for the collision side; however, this also means that the objects cannot pass through each other anymore.

I have a number of objects that I want to be able to pass through each other (while still detecting collisions), suggesting they should be triggers. However, I cannot detect on what side the collisions occur using contact points as described above. Most people seem to get around this by doing an additional line casting test. In the case of ground detection, they cast a line into the ground and test the result.

I originally did something like line casting, except that I tested four smaller circles on top, left, right, and bottom of my player. The problem right now is that the circles to the right and left of the player do not always detect if he is touching walls when his feet are touching. Obviously, I could add more circles near the bottom to deal with this, but it does not seem very scalable. I would expect line casting to have the same problem, not to mention having an extra cost for every single game character who needs extra line casts done (or circle tests if I stick with this method).

Is there a way to use Unity’s collision detection events while both allowing objects to pass through each other AND finding out which direction collisions occurred without extra tests?

When you get the trigger callback, why not use the linear velocity. This is the direction; opposite this could be considered the normal.

2 Likes

How could you use the linear velocity to find the side of collision impact? Aside from accounting for differences in the velocities of two moving objects, I assume size and position differences would also have an effect.

I’m not following exactly what you need and it depends on what you mean by ‘side’. If you mean detecting a collider edge normal and contact points then no, they don’t exist and would need to be calculated explicitly but obviously, contacts with triggers nearly always mean overlapped (often completely) and not an exact contact with a surface.

If you do get a trigger callback then the velocity at that time indicates the direction of travel from which you can assume is the side you ‘entered’ the trigger. If both object are moving then relative velocity can be used as a pseudo collision normal direction. If you pass completely through it and don’t get a callback then you simply tunneled. This situation can only be resolved by projecting collision testing in the direction of travel i.e. ray-casting, adding dummy large triggers surrounding the object (sort of a pre-detection) etc.

As a side-note; there’s a new GetContact API coming which’ll allow you to retrieve any existing contacts without using the collision callbacks. One aspect of this new API is asking for a trigger contact to calculate ‘effective’ contact points. This won’t help if you’re not in contact with a trigger but if you are, it’ll return contact points, normal as if it were not a trigger i.e. the points/normal that Box2D would use to separate them because of the overlap.