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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

[SOLVED] Instantiate Object Snap To Grid

Discussion in 'Scripting' started by jlpeyton, Feb 18, 2020.

  1. jlpeyton

    jlpeyton

    Joined:
    Dec 22, 2017
    Posts:
    57
    Any good documentation to help with instantiating 2d cubes that snap to the grid? The code below when I touch on the screen will instantiate a cube object where I pressed but I need to make it so it locks it to the closest 1x1 grid on the level.

    Code (CSharp):
    1. if (Input.touchCount > 0)
    2.         {
    3.             Touch touch = Input.GetTouch(0);
    4.             Vector2 touchPos = Camera.main.ScreenToWorldPoint(touch.position);
    5.  
    6.             if (touch.phase == TouchPhase.Began)
    7.                 Instantiate(block, touchPos, Quaternion.identity);
    8.         }
     
  2. kdgalla

    kdgalla

    Joined:
    Mar 15, 2013
    Posts:
    4,386
    just add something like:

    touchPos.x = Mathf.Round(touchPos.x);
    touchPos.y = Mathf.Round(touchPos.y);
     
  3. jlpeyton

    jlpeyton

    Joined:
    Dec 22, 2017
    Posts:
    57
    Very simple to incorporate, thank you. I added .5f to the round so it would instantiate to the tile in the background, otherwise it was instantiating on the grid line like such:
    grid.JPG

    Is there some additional precision I could add to better locate where the user pressed? For instance, if I press on the bottom left grid square on the image above it may round and instantiate to the top left or it may round to the bottom right square.
     
  4. unit_dev123

    unit_dev123

    Joined:
    Feb 10, 2020
    Posts:
    989
    i suppose u could use trig to get further precision?
     
  5. Ardenian

    Ardenian

    Joined:
    Dec 7, 2016
    Posts:
    313
    Consider using the Grid Component in your factory that instantiates the cube.

    Consulting the script reference for Grid also helps using it from code.
     
  6. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,835
    Are the lines in your grid exactly 1 Unity game unit apart from each other in world coordinates? If not, you're going to need to round to whatever grid size you are using, not just to the nearest integer.
     
  7. kdgalla

    kdgalla

    Joined:
    Mar 15, 2013
    Posts:
    4,386
    The problem is that you want the corner of the quad to line-up, but the pivot is actually in the center of the quad. Just add 0.5 to your x and y.
     
  8. jlpeyton

    jlpeyton

    Joined:
    Dec 22, 2017
    Posts:
    57
    @Ardenian Each cell in my grid is 1x1. I'm looking through the grid script documentation you linked and noticed a method called GetCellCenterLocal which returns the Vector3 coordinate of the bottom-left of the cell.

    What's currently happening:
    grid.JPG


    I press in the bottom left of quadrant 1, it rounds the position to the center of all 4 quadrants, and depending on if I add + / - .5 to the round method, it will instantiate my block either in quadrant 3 or quadrant 1. This is fine if it's Q1 since I technically clicked inside Q1. But if the location I pressed in Q1 was in the top right corner it would round up and instantiate +1 up and +1 to the right.
     
  9. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,835
    Try adding 0.5 before rounding, and then subtracting 0.5 after rounding. (Or vice versa.)

    Mathf.Round(touchPos + 0.5f) - 0.5f
     
    jlpeyton likes this.
  10. eses

    eses

    Joined:
    Feb 26, 2013
    Posts:
    2,637
    @jlpeyton

    If you want to round your positions to a grid, you can use Floor instead of Round - that way all the clicks inside an imaginary grid cell will round to correct cell, as long as your position is inside the cell rectangle.

    Then if your grid is not aligned to start from 0,0,0 you should add that offset too. And you should also add an offset for your items pivot (how much its pivot is offset from its minimum corner).

    You will also need to take care of the grid size, if it is not 1. Example from my notes:
    Code (CSharp):
    1. // only works with ortho camera
    2. wPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
    3.  
    4. // Get tile position
    5. var tx = Mathf.FloorToInt(wPos.x / tileSize) * tileSize;
    6. var ty = Mathf.FloorToInt(wPos.y / tileSize) * tileSize;
     
  11. jlpeyton

    jlpeyton

    Joined:
    Dec 22, 2017
    Posts:
    57
    This fixed the instantiation positioning and made my day!