0
\$\begingroup\$

I am a Unity newbie and trying to implement a simple building system in a prototype of the game. The scenario is:

  1. Clcik on the UI Button
  2. Move the coursor to the desired position
  3. Click left mouse button and place an object.

Game info I had a Isometric Z as Y grid with child tilemap, already had some simply map enter image description here

I had created a few scripts with separated logic and already tried to implement 2 approaches:

  1. Calculate Vector3Int coordinates of the mouse (x, y) - the coordinates of the tilemap's cell
    Vector3Int GetMousePosition()
    {
        int z = (int)GridManager.Instance.GetActiveTilemap().transform.position.z;
        Vector3 mouseWorldPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        Vector3 mouseWorldPosTranformed = new Vector3(mouseWorldPos.x, mouseWorldPos.y, z);
        Vector3Int pos3d = grid.WorldToCell(mouseWorldPosTranformed);
        return pos3d;
    }

then object is following by coursor by

tempObject.transform.position = position;

here 'position' is a Vector3Int output of the GetMousePosition() function

But the result looks like this:

enter image description here The answer is that the object (blue diamond) is placed in a "normal" coordinates x', y' in point (4; 0). But my grid object has an isometric layout so visually object is placed not in a grid cell But if I change the Grid's layout to rectangular - everything match perfect.

  1. Calculate real coordinates of the mouse using
    Vector3 GetMousePosition()
    {
        Tilemap map = GridManager.Instance.GetActiveTilemap();
        int z = (int)map.transform.position.z;
        Vector2 touchPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        Vector3 cellPos = GridManager.grid.GetComponent<GridLayout> 
        ().LocalToCell(touchPos);
        return cellPos;
    }

and then transform coordinates using grid layout and CellToLocalInterpolated().

tempObject.transform.localPosition = GridLayout.CellToLocalInterpolated(position + new Vector3(0.5f, 0.5f, 0f));

Now visually the result is correct enter image description here

BUT the problem is that now the coordinates is not match grid cell position: enter image description here for example object has coordinates (1.5; 1.5) while tilemap cell is (4; 1) starting from 0 included.

I understand that this is because of Unity has only flat XY coordinates and isometric projection is just visually transformation. Nevertheless this is visually looks fine I already see a problem to match coordinate of grid cells to this coordinates of my objects.

So I am looking for advice.

For now I am thinking of separate object into 2 classes:

  1. ObjectModel. This class is instaintiated using 1st approach and it will have no prefab or any of visual properties.
  2. ObjetView. This class will have an ObjectModel objectModel property, prefab properties and all visual components for visualisation and will instantiated using 2nd approach and visually everything will still looks fine.

But I am still not sure this is a good approach and maybe this could be done much more easier. Bcs for every object I should create at least 2 instance of class.

\$\endgroup\$
5
  • \$\begingroup\$ It looks like instead of tempObject.transform.position = position; you want something like tempObject.transform.position = grid.CellToWorld(pos3d); where pos3d is the Vector3Int cell coordinate you calculated in the previous code block. \$\endgroup\$
    – DMGregory
    Feb 25 at 22:52
  • \$\begingroup\$ Thank you for this advice! But, unfortunatel this leads to the same result as my second approach. What I expected: If I place object to the tilemap cell with coordinates (a, b) I am expecting that Object_x = a, Object_y = b. But it seems this will never happens because objects knows nothing about tilemap cells and their position on game's canvas is determined by their absolute (x, y) coordinates. So it seems the only way is to separate object's logic and game object into 2 classes and game objects, one with physical attributes and another with visual attributes \$\endgroup\$
    – Valeriy
    Feb 26 at 17:05
  • 1
    \$\begingroup\$ Can't you have one class that just stores a separate variable for its tile position, instead of asking the transform for its absolute position? \$\endgroup\$
    – DMGregory
    Feb 26 at 17:23
  • \$\begingroup\$ thank you for this advice. Yes, this would work. I just try to implement some kind of MVC pattern and separate "model" and "view". But may be this is too much and I should not overseparate code \$\endgroup\$
    – Valeriy
    Feb 27 at 18:40
  • \$\begingroup\$ This seems more complicated than it could be. Try writing a project and unproject function instead. You project a unit to get a pixel value, and you unproject a pixel value to get a unit value. \$\endgroup\$
    – mouse
    Feb 29 at 10:09

0

You must log in to answer this question.

Browse other questions tagged .