I have a very basic player in Unity that I coded to collide against objects using Physics.ComputePenetration(...) and it works relatively well. The problem is that I would like more detailed information about where the player hit the collider.
Some things to note:
First of all, the idea of this project is to see if I can replicate the CharacterController's functionality from scratch using ComputePenetration. I am currently trying to replicate the built-in OnControllerColliderHit(...) function, which allows me to get the location of where the hit took place.
Second of all, I am not using a SphereCollider. If I was, then all I would have to do is get the returned direction vector and multiply it by the sphere's radius (along with a couple of other things). But sadly, I am using a CapsuleCollider (maybe there's a way to do the same thing but for a CapsuleCollider, but I have not been able to find one).
What I've tried:
My initial idea was to take the collider that the player hit, hitCollider, and execute this snippet of code:
Vector3 point = hitCollider.ClosestPoint(player.transform.position);
to get the closest point on the hit collider. From there, I could call
Vector3 finalPoint = player.collider.ClosestPoint(point);
on the player to get its closest point to the hit collider's closest point. It's very confusing, but it works pretty well. There's only one drawback, however: I plan on using ProBuilder to do a lot of my level design, and you cannot call ClosestPoint on a MeshCollider that does not have convex set to true, which is a majority of meshes in ProBuilder.
I thought of a couple of other things, like maybe I could invert the direction and then do some (not-so) hacky math to get the contact point, etc. but nothing seemed to work as a full-blown solution.
Closing thoughts:
I'm beginning to think that it's not technically possible. Which is true if you think about it, because when two objects intersect, there's no single point that defines it, it's an entire volume that does so. But getting the average position of that volume would (maybe?) be the solution.
Any ideas?
Thank you in advance!
For anyone else who was curious, I found the solution. When
Physics.ComputePenetration(...)betweenourColliderandselectedColliderdetects a collision, make sure to de-penetrate FIRST, then do the following:Call a
Physics.CapsuleCast(...), but make sure thatpoint1,point2, andradiusare slightly smaller values (maybe 0.001) than the original capsule's size. This is because theCapsuleCastwill think that it's intersecting with theselectedColliderand will therefore just go straight through it, which you don't want. Then just make yourdirectionthe negative direction that was output fromPhysics.ComputePenetration(...).So your code ends up looking like this: