Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by Raja-Unity · Jun 06, 2021 at 05:56 PM · physics3dmathspacevectors

Calculate collision between 2 rotated boxes without using BoxCollider (MATH)

I am developing a 3D grid system for my game so I'll have to calculate box collisions dozens of times per frame. I need to find a way to calculate the collision between 2 boxes given the position, size, and rotation. Adjacent boxes shouldn't detect collision. NOTE: I don't know any advanced math

It would be preferred if you fill in the gaps of the following function:

     bool Intersects(Vector3 positionA, Vector3 sizeA, Quaternion rotationA, Vector3 positionB, Vector3 sizeB, Quaternion rotationB)
     {
         //content...
         //returns true if both boxes collide
     }
     Intersects(new Vector3(0f, 0f, 0f), Vector3.one, Quaternion.Euler(Vector3.zero), new Vector3(1f, 0f, 0f), Vector3.one, Quaternion.Euler(Vector3.zero)); 
 //adjacent boxes should return FALSE
Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

2 Replies

· Add your reply
  • Sort: 
avatar image
1
Best Answer

Answer by Bunny83 · Jun 07, 2021 at 02:45 AM

Well, there are several ways how to do a box - box intersection test. Most physics systems would first apply an AABB check to determine if the boxes could even possibly collide and only do the actual collision test when necessary. However if you really only have two boxes you want to check, that probably doesn't matter.


One way would be to use the seperating axis theorem. This involves to project all corners of both boxes onto the normals of each shape and check for an overlap there by checking the min / max value along those axis. While in 2d using the 4 axis (two for each box) is enough, in 3d it is not sufficient to check the 6 (3 for each box) axis. In addition to those we also have to check all the crossproduct combinations between the 3 axes of both boxes. So we have to check 6+ 3*3 == 15 axes in the worst case. The great thing about this approach is once you found a seperating axis, you an immediately terminate and return false. Only when all 15 checks show an overlap, the boxes really overlap. I quickly hacked this together

 private struct Box
 {
     public Vector3 pos, n1, n2, n3;
     public float min, max;
     private void UpdateMinMax(Vector3 aPos, ref Vector3 aNormal)
     {
         float p = Vector3.Dot(aPos, aNormal);
         if (p > max) max = p;
         if (p < min) min = p;
     }
     public void GetMinMax(ref Vector3 aAxis)
     {
         min = float.PositiveInfinity;
         max = float.NegativeInfinity;
         UpdateMinMax(pos + n1 + n2 + n3, ref aAxis);
         UpdateMinMax(pos + n1 + n2 - n3, ref aAxis);
         UpdateMinMax(pos + n1 - n2 + n3, ref aAxis);
         UpdateMinMax(pos + n1 - n2 - n3, ref aAxis);
         UpdateMinMax(pos - n1 + n2 + n3, ref aAxis);
         UpdateMinMax(pos - n1 + n2 - n3, ref aAxis);
         UpdateMinMax(pos - n1 - n2 + n3, ref aAxis);
         UpdateMinMax(pos - n1 - n2 - n3, ref aAxis);
     }
 }
 
 private struct TwoBoxes
 {
     public Box A, B;
     // returns true if there is no overlap, false if they do overlap
     public bool SAT(Vector3 aAxis)
     {
         A.GetMinMax(ref aAxis);
         B.GetMinMax(ref aAxis);
         return A.min > B.max || B.min > A.max;
     }
 }
 
 public static bool Intersects(Vector3 positionA, Vector3 sizeA, Quaternion rotationA, Vector3 positionB, Vector3 sizeB, Quaternion rotationB)
 {
     TwoBoxes data = new TwoBoxes();
     data.A.pos = positionA;
     data.A.n1 = rotationA * Vector3.right * sizeA.x;
     data.A.n2 = rotationA * Vector3.up * sizeA.y;
     data.A.n3 = rotationA * Vector3.forward * sizeA.z;
     data.B.pos = positionB;
     data.B.n1 = rotationB * Vector3.right * sizeB.x;
     data.B.n2 = rotationB * Vector3.up * sizeB.y;
     data.B.n3 = rotationB * Vector3.forward * sizeB.z;
     if (data.SAT(data.A.n1)) return false;
     if (data.SAT(data.A.n2)) return false;
     if (data.SAT(data.A.n3)) return false;
     if (data.SAT(data.B.n1)) return false;
     if (data.SAT(data.B.n2)) return false;
     if (data.SAT(data.B.n3)) return false;
 
     if (data.SAT(Vector3.Cross(data.A.n1, data.B.n1))) return false;
     if (data.SAT(Vector3.Cross(data.A.n1, data.B.n2))) return false;
     if (data.SAT(Vector3.Cross(data.A.n1, data.B.n3))) return false;
     if (data.SAT(Vector3.Cross(data.A.n2, data.B.n1))) return false;
     if (data.SAT(Vector3.Cross(data.A.n2, data.B.n2))) return false;
     if (data.SAT(Vector3.Cross(data.A.n2, data.B.n3))) return false;
     if (data.SAT(Vector3.Cross(data.A.n3, data.B.n1))) return false;
     if (data.SAT(Vector3.Cross(data.A.n3, data.B.n2))) return false;
     if (data.SAT(Vector3.Cross(data.A.n3, data.B.n3))) return false;
     return true;
 }

I don't have time to test this right now, but I did just check it quickly in .NET fiddle and the first tests seems to work. This solution should not allocate any memory. First I thought to actually passing all the data to the nested functions. However that would be rather slow since all arguments have to be pushed onto the stack. Then I thought I could simply pack the data into a struct and pass that by ref to avoid the massive data copy. Then I realised I could simply place the methods directly into the structs ^^. This cuts down the argument count and should be a bit faster (at least in theory) and is a bit cleaner / easier to read.

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Raja-Unity · Jun 08, 2021 at 03:16 AM 0
Share

This solution definitely works although as a note for future viewers, I first perceived the sizeA and sizeB parameters to function as the total size of the boxes but later found out they functioned as box extents. Halving those two parameters at the beginning of the function fixed the problem for me. Boxes that are directly adjacent to each other will also register collision to be true although I've decided to just reduce the box sizes by 0.01f to solve this issue.

avatar image
0

Answer by logicandchaos · Jun 06, 2021 at 07:13 PM

There are many built in methods for detecting collisions:

Physics2D.OverlapBox https://docs.unity3d.com/ScriptReference/Physics2D.OverlapBox.html

Vector2.Distance https://docs.unity3d.com/ScriptReference/Vector2.Distance.html

Raycasts https://docs.unity3d.com/ScriptReference/Physics.Raycast.html

Collider2D.IsTouching https://docs.unity3d.com/ScriptReference/Collider2D.IsTouching.html

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Raja-Unity · Jun 06, 2021 at 08:24 PM 0
Share

I did consider these solutions, although I thought it was quite overkill to have to instantiate a GameObject with a BoxCollider to check for physics raycasts only for the use in one function. I am developing a 3D grid system for my game so I'll have to calculate box collisions dozens of times per frame.

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

227 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Player gets stuck into object after collision 2 Answers

How to Buffet an object floating in space? 1 Answer

Collision impact force 1 Answer

OnTriggerEnter and OnTriggerStay often not registering 1 Answer

Objects stuck dragging across floor 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges