- Home /
How can I find on which side of an EdgeCollider2D a collision takes place?
Hello, I have a terrain GameObject with an EdgeCollider2D and a Character GameObject with a Random Collider. I want to find on which side of the EdgeCollider2D the Collision is happening on whenever OnCollisionEnter2D is called. I wrote these 3 functions to kinda do this, but they are too slow (there is a ~3-frame lag spike whenever my GameObject collides with Terrain) and sometimes imprecise.
Is there any faster and more precise way for me to do this?
Edit: I have a small typo on the code at Pastebin, the first function is not supposed to have the 'Alt' at the end...
Example image:
It's been 4 hours, mods...I kinda want to get this thing fixed by tomorrow...
Sorry for the wait; I think Unity just exploded in popularity; the mod queue stays utterly swamped since they changed their licensing policy.
I have zero familiarity with 2D or edge colliders; do you not know which edge collider was touched by virtue of its OnCollision event being raised?
You must clarify what you mean by "which side of the collider".
If you want to know north or south, it should be sufficient to measure the difference between the collision point Y and the object origin Y; the sign of the difference would give meaningful information about whether the colliding object is "above" or "below" the line.
If you mean "where along the line was the collision" this can likewise be solved with some simple arithmetic involving the start/end points of the line and the collision point.
Diagrams are helpful (much obliged for the extra mile) but the phrasing of the question leaves too much room for interpretation. Please consider a follow-up comment if what I've shared wasn't helpful.
Best,
Regarding your first question: Yes, I do know with which EdgeCollider I've collided with (by marking the Edge Collider's tag as "Terrain" and then checking for it).
To clarify "which side of the collider": I want to know on which line segment of the EdgeCollider2D the collision has happened.
So, I meant "where along the line was the collision", as you specified yourself. I believe I found a faster way of doing this but it still produces lag spikes whenever I run it in the editor... It's an optimization of the CheckLinePoint function, which checks ratios ins$$anonymous$$d of the triangle law(a+b>c for each side), so it no longer needs to calculate sqrt(for the length of each line segment). But, as I said it still lags in the editor. Is there a possibility it'll run faster if I export it?
I can think of some hacky ways of solving your problem.
The first would just be to use multiple colliders, one for each line segment. This is straightforward, but it would probably involve lots of clicking.
Alternatively, if you know the position of the collision relative to the terrain you can guess which line you're on. For example, if line0 covers x values from 0 to 1, and the collision occurs between x values of 0 and 1, then you know that the collision involves line0.
The first way would make it really difficult to create any sort of terrain quickly. I've though of the second way, but the problem is that the EdgeCollider can be concave, thus there may be more than one line per X coordinate...
By the way, I just added the FPS Counter I found on the Unity Wiki and after building my game I don't get such a bad FPS drop as in the editor. Although I'm not sure whether this won't be a problem with EdgeColliders with 200+ lines...
I think I should pass this entire thing as a feature request, since I'd imagine that it's pretty necessary when working with EdgeColliders and PolygonColliders.
Answer by moxiewhimsy · Apr 06, 2015 at 04:06 PM
Does your terrain tend to continue in one direction as in your example?
If so, you could reduce the number you check through by whether the x position of the contact point is greater or less than the x position of the middle point. Then find whether it's greater or less than the middle point of that half of the points. Then whether it's ... and so on.
This should give you mostly logarithmic time complexity.
Though, if your terrain overlaps in the x position at all, you may need to intentionally include more points in the final check loop.
Sadly, my terrain can overlap in the x position and it does...a lot, so achieving O(log x) would be pretty difficult without wasting a lot of memory. An option would be to have a map(I'm pretty sure there are maps in C#, I come from C++ :D) with an X coordinate as it's index and an array of line numbers for its value. Then I can do a Binary Search through the map's indexes and after that check my point with all the values. I believe that would be the ideal solution to this problem.
Still, I believe this should be part of the EdgeCollider2D and PolygonCollider2D API.
Edit: I will mark your answer as correct, since it kinda is, although I believe this comment is a more detailed solution...
Certainly. In C#, if a $$anonymous$$ap is to your liking, a Dictionary could also work. It would more than pay off efficiency-wise. And yes, in the case of overlap that's the better approach by many fold.