How to get collision data from Physics.OverlapBox()?

How to get collision data from Physics.OverlapBox()?



I'm trying to find other methods of registering collisions (other than OnCollisionEnter() and OnCollisionExit()). I'm currently using Physics.OverlapBox(), but I need more information about the collision; i.e., normal, point.


OnCollisionEnter()


OnCollisionExit()


Physics.OverlapBox()



I can use Physics.BoxCast(), but the problem is that it moves a box a given distance, and using maxDistance = 0f won't work.


Physics.BoxCast()


maxDistance = 0f



I need a method of checking for collisions similar to Physics.OverlapBox() except in that it would also return information about all collisions in the cast.


Physics.OverlapBox()



Any help is appreciated. Thanks.






Physics.OverlapBox() returns all information you could possibly need.

– Sandro Figo
Sep 15 '18 at 1:53



Physics.OverlapBox()






Physics.BoxCastAll with a distance of FLT_EPSILON?

– Draco18s
Sep 15 '18 at 4:50


Physics.BoxCastAll


FLT_EPSILON




2 Answers
2



You can use OverlapBox and use Collider's ClosestPoint to select a single point of overlap, and use that to make your collision calculations.


OverlapBox


Collider


ClosestPoint


Collider cols = Physics.OverlapBox(...);
Vector3 myPosition = transform.position; // for example

foreach (Collider col in cols)
Vector3 closestPoint = col.ClosestPoint(myPosition);
Vector3 positionDifference = (closestPoint-myPosition);
Vector3 overlapDirection = positionDifference.normalized;



This overlapDirection will point in the direction away from the the position you use in ClosestPoint to the center of each colliding collider. If you want something based on the surface of your object, what you can do is use that overlap direction to place a raycast aimed at your object, to find the normal that way:


overlapDirection


ClosestPoint


// ...

foreach (Collider col in cols)
Vector3 closestPoint = col.ClosestPoint(myPosition);
Vector3 positionDifference = (closestPoint-myPosition);
Vector3 overlapDirection = positionDifference.normalized;

RaycastHit hit;
int layerMask = 1; // Set to something that will only hit your object
float raycastDistance = 10.0; // something greater than your object's largest radius,
// so that the ray doesn't start inside of your object
Vector3 rayStart = myPosition + overlapDirection * raycastDistance;
Vector3 rayDirection = -overlapDirection ;

if (Physics.Raycast(rayStart, rayDirection, out hit, Mathf.Infinity, layerMask))
Debug.Log(hit.normal);
Debug.Log(hit.position);
else
// The ray missed your object, somehow.
// Most likely it started inside your object
// or there is a mistake in the layerMask







Thank you. I understand your approach, but there is a flaw-- imagine if the object was hit by a point on the surface of a collider, but another point on the same collider was closer to myPosition than the actual collision point. We would get false data about the collision's normal, position, etc. The only fix to this would be if we could somehow get the closest distance and direction between 2 colliders.

– blackhole
Sep 16 '18 at 4:06



myPosition



Your concern, expressed in the comment to the first answer is valid, but the bad news is that there is no simple trick to go around it. What you should be looking for is called continuous collision detection with a simplified version described in my answer on a somewhat similar matter:



Basically, for each moving object in your scene you have to calculate
moment of next collision within the fraction of the frame 0<t0<1,
then advance positions to this moment t0 within the frame, update
velocities due to collision and proceed further to the next collision
t0<t1<1, until you reach time of tn=1 (end of frame), making sure
you don't get stuck in a the middle of the frame due to rounding of
calculation or "cornered" objects. For spherical colliders, that is
usually done by using capsule vs capsule (for pairs of objects)
intersection and capsule vs box for the boundaries.


0<t0<1


t0<t1<1


tn=1



In oppose to the simple engine from the answer I'm referring to, Unity has continuous collision detection.
So you can enable continuous collisions and continuous dynamic which computationally is very expensive.



You can also try using RigidBody.SweepTest which returns the closest collision information. Notice that even though there is also RigidBody.SweepTestAll, it doesn't help much. Not only because it returns only first 128 collisions, but also because it doesn't process them as there is no reflection. For physically correct behaviour you have to do what described above - advance time till the first collision and update velocities. Either with the physics engine or by yourself. This is very costly and not many games are doing that even cheating by using simplified objects (spheres are the cheapest ones as two swept spheres are two capsules and their intersection is a relatively cheap calculation), but amount of steps, especially in the "cornered" case when objects have nowhere to go and therefore are constantly colliding could be very large and such cases happen more than one can expect.



For complex objects you unlikely can do better than SweepTest, unless you trigger it based on the simpler primitives, such as Physics.BoxCast or Physics.SphereCast. Again, even though there are Physics.BoxCastAll and Physics.SphereCastAll they are not particularly useful as only first collision is guaranteed to occur. Those xxxCastAll are the functions you wrote you were looking for, so give it a try, they might work well enough for your use case.


Physics.BoxCast


Physics.SphereCast


Physics.BoxCastAll


Physics.SphereCastAll



Thanks for contributing an answer to Stack Overflow!



But avoid



To learn more, see our tips on writing great answers.



Required, but never shown



Required, but never shown




By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

Edmonton

Crossroads (UK TV series)