Cube instantiaes on wrong side of the plane

I am spawning cube on a plane by clicking and getting the hit.point from Raycast. But sometimes cube spawn on the other side of the plane

I am trying to make the cubes snap into positin an not overlap by dividing the plane into Grid Cells and then converting the grid coordinates to World Position, and then spawn the cube on this position.

Instantiating:

  int x, y, z;
                grid.GetCOORD(hit.point, out x, out y, out z);

                Instantiate(cube, grid.GetWorldPosition(x, y, z) + Vector3.one * grid.CellSize * 0.5f, Quaternion.identity);

This is the conversion methods:

    public Vector3 GetWorldPosition(int x, int y, int z)
    {
        return new Vector3(x, y, z) * cellSize + pivot.position;
    }

   public void GetCOORD(Vector3 worldPosition, out int x, out int y, out int z)
    {
        x = Mathf.FloorToInt((worldPosition - pivot.position).x / cellSize);
        y = Mathf.FloorToInt((worldPosition - pivot.position).y / cellSize);
        z = Mathf.FloorToInt((worldPosition - pivot.position).z / cellSize);
    }

Everything works fine on the floor plane, but walls dont behave correctly.

Any help is appreciated, thanks.

I expect this is caused by some floating point error, I would expect this behaviour to happen if my completely flat wall plane was right on the boundary between the two cells.

I’d recommend testing whether this is the case as it is at this point just an assumption about what’s going wrong. If this is the case then I’d expect to see the value that you floor inside your GetCOORD function to be very close to an integer before flooring. If this doesn’t happen then my hypothesis is wrong and you can ignore the rest of the answer!

Explanation: for simplicity let’s say your cell size is 1 and pivot position is (0,0,0). If your wall is at (0,0,2) and facing the z-direction then when you click it you might get a hit location of (-1.23123, 2.82391, 2.0001) or (-1.23123, 2.82391, 1.999998). As you can see the results’ z-positions are very close to 2 but not exactly 2. This is called floating point error and exists because computers won’t represent floating point numbers (numbers with a fractional component) exactly.

There are a number of ways you can mitigate this and which you choose depends on how you plan to create your levels in the future:

If you decide that walls will always exist on these boundaries then you could add your hit’s normal vector to your hit point to get a position that’s inside the cell. You’d have to scale the normal so it’s smaller than your cell size.

grid.GetCOORD(hit.point + hit.normal * grid.CellSize * 0.5f, out x, out y, out z);

Alternatively you could use very thin cubes instead of planes to represent the walls, making sure that the sides of the wall that your raycast would hit would be clearly on one side of the boundary rather than ambiguously close to it.