Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Find the four corners of a plane

Discussion in 'Scripting' started by v_chs, Nov 27, 2020.

  1. v_chs

    v_chs

    Joined:
    Dec 11, 2019
    Posts:
    64
    I try to create a grid that will dynamically fill a scene with 1x1 cells, according to plane size. (Attached img)

    For now, I get the plane's bound size and I set a starting point to start filling the scene, according to the cellSize I chose.

    Is there any way of finding this starting point (corner - bottom left) and the end point (top - right corner)of the plane dynamically?


    Code (CSharp):
    1.     private void GenerateGrid() {
    2.         RaycastHit hitInfo;
    3.         Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
    4.         var x = 2.1f; // Starting point coordindate
    5.         var z = 2.1f; // Starting point coordindate
    6.         for (var i = 0; i < cellsInXaxis; i++) {
    7.             for (var j = 0; j < cellsInZaxis; j++) {
    8.                 if (Physics.Raycast(ray, out hitInfo) && counter <= (cellsInXaxis * cellsInZaxis)) {
    9.                     PlaceCubeNear(new Vector3(x, 0.474f, z));
    10.                     counter++;
    11.                 }
    12.                 else {
    13.                     return;
    14.                 }
    15.                 z += cellsSize;
    16.             }
    17.             z = 2.1f;
    18.             x += cellsSize;
    19.         }
    20.     }
     

    Attached Files:

  2. Terraya

    Terraya

    Joined:
    Mar 8, 2018
    Posts:
    646
    The first left corner is the first cell you make,
    the right top corner is the last cell in the first row,
    the bottom left corner is the first cell in the last row,
    the bottom right corner is the last cell in the last row

    hope that helps :)
     
    v_chs likes this.
  3. v_chs

    v_chs

    Joined:
    Dec 11, 2019
    Posts:
    64
    Sure, but I set the coords of the first cube - the starting point - manually ( x = z = 2.1f)

    This is what I'm looking for -how could I find these.

    Thanks for the reply! :)
     
    Lastyyy likes this.
  4. Terraya

    Terraya

    Joined:
    Mar 8, 2018
    Posts:
    646
    Ok, i think i need the explanation of "how could i find these",

    what do you mean by this, the cell or the GameObject?
    As i can see you have the reference for the cell so you mean the Box(GameObject) itself?

    Where do you Instantiate your Boxes :eek:?
     
    v_chs likes this.
  5. v_chs

    v_chs

    Joined:
    Dec 11, 2019
    Posts:
    64
    Ι avoided attaching all the code because I wanted to focus on the plane and its corners. That's why I attached a part of the code.

    I think it's irrelevant the way I create the cubes, because the point of finding the vertices of the plane, is before this.

    I have the script attached on the plane (floor of the scene), and on this plane, I generate cells, according to their size. The grid starts from a static starting point. If I move the plane right, the grid will start from the same starting point, so it won't generate cells dynamically.
     
  6. Terraya

    Terraya

    Joined:
    Mar 8, 2018
    Posts:
    646
    Ahhh now i get it :D,

    humm let me think
     
  7. v_chs

    v_chs

    Joined:
    Dec 11, 2019
    Posts:
    64
    Thanks a lot! :)

    I found some solutions by using the vertices, but I didn't manage to make it work. :(
     
    Terraya likes this.
  8. roykoma

    roykoma

    Joined:
    Dec 9, 2016
    Posts:
    176
    If you are using the default Plane of Unity this can be a quite simple task.
    The default Plane mesh is 5x5 meters in size - so you can get the local coordinates of the corners using:
    • new Vector3(-5, 0, 5) (Top Left)
    • new Vector3(5, 0, 5) (Top Right)
    • new Vector3(-5, 0, -5) (Bottom Left)
    • new Vector3(5, 0, -5) (Bottom Right)

    You have a few options on how to use this information. Here are three of the easier ones:

    1. Create Child objects
    Create new GameObjects and parent them to the plane. Then set their localPositions to the values above and get the worldPositions using .position.

    An example getting all 4 corner positions using this method:
    Code (CSharp):
    1. var go = new GameObject(); //Create an empty GameObject
    2. go.transform.SetParent(planeTransform); //parent the new GameObject to the Plane
    3.  
    4. go.transform.localPosition = new Vector3(-5, 0, -5); //Set LocalPosition to Bottom Left Corner
    5. Vector3 bottomLeft = go.transform.position; //Get World Position of Bottom Left Corner
    6.  
    7. go.transform.localPosition = new Vector3(5, 0, -5); //Set LocalPosition to Bottom Right Corner
    8. Vector3 bottomRight= go.transform.position; //Get World Position of Bottom Right Corner
    9.  
    10. go.transform.localPosition = new Vector3(-5, 0, 5); //Set LocalPosition to Top Left Corner
    11. Vector3 topLeft = go.transform.position; //Get World Position of Top Left Corner
    12.  
    13. go.transform.localPosition = new Vector3(5, 0, 5); //Set LocalPosition to Top Right Corner
    14. Vector3 topRight = go.transform.position; //Get World Position of Top Right Corner
    15.  
    16. Destroy(go, 0); //Destroy the empty GameObject again
    2. Use Matrix Conversion
    Create a Matrix4x4 using the planes localToWorldMatrix and use it's MultiplyPoint3x4 method to convert the local positions to world space coordinates.

    An example getting all 4 corner positions using this method:
    Code (CSharp):
    1. Matrix4x4 localToWorld = planeTransform.localToWorldMatrix; //Create a Matrix in the planes LocalSpace
    2. var topLeftPos = localToWorld.MultiplyPoint3x4(new Vector3(-5, 0, 5)); //Get the Top Left Position in WorldSpace
    3. var topRightPos = localToWorld.MultiplyPoint3x4(new Vector3(5, 0, 5)); //Get the Top Right Position in WorldSpace
    4. var bottomLeftPos = localToWorld.MultiplyPoint3x4(new Vector3(-5, 0, -5)); //Get the Bottom Left Position in WorldSpace
    5. var bottomRightPos = localToWorld.MultiplyPoint3x4(new Vector3(5, 0, -5)); //Get the Bottom Right Position in WorldSpace
    3. Create Child objects below the plane and set their local positions to the above values
    You can then simple get their WorldPosition using
    transform.position


    4. Alternative
    If you don't use the default plane it's probably best to get the corners using the mesh bounds like so:
    Code (CSharp):
    1. MeshFilter meshFilter = GetComponent<MeshFilter>(); //Get the Mesh Filter of the plane - if it's on another object, you'll have to reference this instead. Also: Don't use GetComponent in Update!
    2. Vector3 extends = meshFilter.mesh.bounds.extents; //Get the extends of the meshs bounds
    3. Vector3 bottomLeftPosition = new Vector3(-extends.x, 0, -extends.z); //Get the Bottom Left Position in LocalSpace
    4. Vector3 bottomRightPosition = new Vector3(extends.x, 0, -extends.z); //Get the Bottom Right Position in LocalSpace
    5. Vector3 topLeftPosition = new Vector3(-extends.x, 0, extends.z); //Get the Top Left Position in LocalSpace
    6. Vector3 topRightPosition = new Vector3(extends.x, 0, extends.z); //Get the Top Right Position in LocalSpace
    You can then convert these Positions from Local Space to WorldSpace using option 1 or 2, or using transform.TransformPoint (See the following posts)

    Hope I could help.

    Kind Regards,
    Roy

    Edited: Changed Typo in Option 4 (I wrote WorldSpace before, but the positions you get are in LocalSpace)
     
    Last edited: Dec 1, 2020
  9. roykoma

    roykoma

    Joined:
    Dec 9, 2016
    Posts:
    176
    Just wanted to add, that transform.TransformPoint is another easy option, that should be mentioned here :)
     
    v_chs likes this.
  10. v_chs

    v_chs

    Joined:
    Dec 11, 2019
    Posts:
    64

    Τhe alternative 4 is the most suitable for me, as I want it to be completely dynamic. So, I want in every plane that a user creates to read it's corner coordinates (x, y, z). Unfortunately, the bottomLeftConer of your code -in alternative 4- returns (-5.0, 0.0, -5.0), far away from the bottom left corner of the plane. e.g. when I put a cube in the bottom left corner I get the position (1.2, 1, 1.1).

    Do I miss something?

    Thank you, anyway, for the help!
     
  11. roykoma

    roykoma

    Joined:
    Dec 9, 2016
    Posts:
    176
    I think what I wrote was a bit confusing - Option 4 is just a way to get the local coordinate (also made a typo there and wrote worldspace accidentally) of the edges without knowing them beforehand.

    The extents give you the coordinates in local space, so you'll still have to translate these to WorldSpace. An example of how to do this using transform.TransformPoint (You could also use option 1 or 2 of my first post to do this):
    Code (CSharp):
    1. var planeTransform = transform; // I just get the current transform here - ideally this would be a reference instead
    2. MeshFilter meshFilter = GetComponent<MeshFilter>(); //Get the Mesh Filter of the plane - if it's on another object, you'll have to reference this
    3. Vector3 extends = meshFilter.mesh.bounds.extents; //Get the extends of the meshs bounds
    4. Vector3 bottomLeftPosition = new Vector3(-extends.x, 0, -extends.z); //Get the Bottom Left Position in Local Space
    5. var bottomLeftWorldSpacePosition = planeTransform.TransformPoint(bottomLeftPosition); //Translate the Position to WorldSpace
    6. Debug.Log(bottomLeftWorldSpacePosition); //Log into console
    Sorry for the confusion!
     
    Last edited: Dec 1, 2020
    v_chs_2 likes this.
  12. v_chs

    v_chs

    Joined:
    Dec 11, 2019
    Posts:
    64
    No need to say sorry. You try to help here :)

    Thanks a lot, again! I'll try this approach
     
  13. roykoma

    roykoma

    Joined:
    Dec 9, 2016
    Posts:
    176
    I just like my answers to be error and confusion free, so people reading them in the future can get what they need without additional need to ask :)

    I have to stress again though, that if you are using the default planes (for example by using
    GameObject.CreatePrimitive(PrimitiveType.Plane)
    ) its local bottom left corner will ALWAYS be
    (-5.0, 0.0, -5.0)
    - it doesn't matter how it is scaled or placed - so there would be no reason to get the bounds from the mesh.
    A simple
    planeTransform.TransformPoint(new Vector3(-5.0, 0.0, -5.0))
    will easily give you the bottom left corner in world space, no matter what position or scale the plane is at.
     
    v_chs likes this.
  14. v_chs

    v_chs

    Joined:
    Dec 11, 2019
    Posts:
    64
    It works like a charm :)

    Thanks a lot! You helped me a ton!