Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

How should colliders interact in 3D grid system?

Discussion in 'Physics' started by C4lv1n, Jan 19, 2021.

  1. C4lv1n

    C4lv1n

    Joined:
    Jun 21, 2018
    Posts:
    7
    I'm working on a game that starts with a 3x3 grid of nine cubes and grows through the grid in any direction on each axis. Essentially, cubes are added in sets of three randomly, and I need each cube to have a method of checking what other cubes are currently around it - on every side and diagonally.

    Can anyone steer me in the right direction?

    Right now, I have a collider on each cube that is slightly bigger than the cube. I'm using OnTriggerEnter in a script on each cube to get all of colliders overlapping with it, and then am attempting to set bools in another script on the cube based on what's colliding.

    Each cube has a collider with 'is trigger' set and a rigidbody that 'is kinematic'. Collisions are detected and some of my bools are being set but the results are inconsistent and the bools seem to be toggling.

    I've never used colliders like this and am wondering if my collider/rigidbody setup is incorrect, and I'm sure plenty of games have to do something simlar.

    Thanks!
     
  2. AlTheSlacker

    AlTheSlacker

    Joined:
    Jun 12, 2017
    Posts:
    326
    Would it not be easier to raycast a short distance from the surface of the cube and see if you get a hit?
     
    C4lv1n likes this.
  3. C4lv1n

    C4lv1n

    Joined:
    Jun 21, 2018
    Posts:
    7
    Thanks for the reply, AITheSlacker.

    Maybe it would be, but would it be possible to get the 'diagonal' cubes that way?

    As the grid builds out, in theory, a single cube could have 26 other cubes touching an edge or corner - if the grid ever built out to a full 3x3x3 grid with 27 cubes, the one in the center touches the other 26.
     
  4. AlTheSlacker

    AlTheSlacker

    Joined:
    Jun 12, 2017
    Posts:
    326
    Ah I was imagining an offset between the cubes, my bad. I think I would be more inclined to have a manager script on each cube that kept track of its neighbours and allowed those cubes to register their creation / destruction with it. Sounds like some sort of event system, but this is not something I know much about (perhaps the scripting forum would be a better bet?). I think trying to do this with triggers will be difficult when there is no clearance.

    Edit: Or a single game manager that tracked creation / destruction of all cubes that you query as you need?
     
    Last edited: Jan 19, 2021
    C4lv1n likes this.
  5. C4lv1n

    C4lv1n

    Joined:
    Jun 21, 2018
    Posts:
    7
    Got it - thanks again for the reply! I'll try coming up with a different approach.
     
  6. C4lv1n

    C4lv1n

    Joined:
    Jun 21, 2018
    Posts:
    7
    A single game manager would be nice. I haven't thought of a way to make that work yet though. The grid would be expanded upon by the players so the shape of it is unpredictable, e.g. players could add a vertical stack of three cubes on top of any existing cubes.
     
  7. BakeMyCake

    BakeMyCake

    Joined:
    May 8, 2017
    Posts:
    175
    I think the right direction might be to not involve physics in this. You have described something that is solved by storing your cubes internally in a reasonable format. Remember that graphics(cubes in your scene) and internal game logic entities(in your C# scripts) don't need to be coupled. You can represent your grid in any spatial-friendly form you like, making it easier to access this sort of information without making the engine do extra calculations.

    If you can live with a hard defined limit to the size of the grid then multidimensional arrays are the simplest solution, otherwise you need some dynamically expanding data structure.
     
    C4lv1n and AlTheSlacker like this.
  8. C4lv1n

    C4lv1n

    Joined:
    Jun 21, 2018
    Posts:
    7
    Thanks for the reply, BakeMyCake.

    Am I understanding correctly that you're saying I need some sort of 'coordinate' system to identify which cubes are active and use that for any further methods?

    At this point, I'm not sure I can live with a hard defined limit to the size of the grid, but your comment gave me an idea for something to try.
     
  9. BakeMyCake

    BakeMyCake

    Joined:
    May 8, 2017
    Posts:
    175
    Yes, that is another way you can describe what I'm suggesting. I was thinking from the "where can I store this data" and you are describing it as "how do I address it", but I believe you have the right idea.

    I gave your no limit requirement some thought and I think you can store your cubes internally as a dictionary with the grid coordinates as the key. To find out if a cube exists you just check if a key with such coordinates exists in the dictionary, and to check adjacency you increment the coordinates and check if anything is there.

    Here is an example of how it can be done in code:
    Code (CSharp):
    1.    struct CoordinateKey: IEquatable<CoordinateKey>
    2.     {
    3.       public readonly int X, Y, Z;
    4.  
    5.       public CoordinateKey(int x, int y, int z)
    6.       {
    7.         X = x;
    8.         Y = y;
    9.         Z = z;
    10.       }
    11.  
    12.       public bool Equals(CoordinateKey other)
    13.       {
    14.         return X == other.X && Y == other.Y && Z == other.Z;
    15.       }
    16.  
    17.       //this is generated by visual studio, maybe it can be improved
    18.       public override int GetHashCode()
    19.       {
    20.         int hashCode = -307843816;
    21.         hashCode = hashCode * -1521134295 + X.GetHashCode();
    22.         hashCode = hashCode * -1521134295 + Y.GetHashCode();
    23.         hashCode = hashCode * -1521134295 + Z.GetHashCode();
    24.         return hashCode;
    25.       }
    26.     }
    27.  
    28.     static void TestDictionary()
    29.     {
    30.       var d = new Dictionary<CoordinateKey, string>();
    31.       d.Add(new CoordinateKey(0, 0, 0), "original");
    32.       d.Add(new CoordinateKey(0, 0, 1), "0 0 1");
    33.       d.Add(new CoordinateKey(0, 1, 1), "0 1 1");
    34.       d.Add(new CoordinateKey(0, 1, 2), "0 1 2");
    35.  
    36.       var k = new CoordinateKey(0, 0, 1);
    37.       if(d.TryGetValue(k, out string v))
    38.       {
    39.         Console.WriteLine(v);
    40.       }
    41.    
    Disclaimer: code quality may be bad.
     
    C4lv1n likes this.
  10. C4lv1n

    C4lv1n

    Joined:
    Jun 21, 2018
    Posts:
    7
    Thanks a lot! I haven't used dictionaries before so I'll need to explore this further to fully understand it.

    I've made some progress on my scripts and have found a way to make it work (for now at least) by tracking the position of the cubes relative to each other, and adding/removing cubes from Lists as I go. The code seems a little clunky though. I appreciate you offering help.