Search Unity

  1. Looking for a job or to hire someone for a project? Check out the re-opened job forums.
    Dismiss Notice
  2. Unity 2020 LTS & Unity 2021.1 have been released.
    Dismiss Notice
  3. Good news ✨ We have more Unite Now videos available for you to watch on-demand! Come check them out and ask our experts any questions!
    Dismiss Notice

HELP!! Great problem with Iso Grid -> Tilemap

Discussion in 'Scripting' started by Chaosgod_Esper, Apr 4, 2016.

  1. Chaosgod_Esper

    Chaosgod_Esper

    Joined:
    Oct 25, 2012
    Posts:
    295
    Hi there..

    Since over 6 Months i want to create an Isometric Terrain mapper.
    This is my Current isometric Grid, and how the Tilemap is structured with that:


    This is my current SceneView Editor approach to calculate the Tilemap position of the Tile, the mouse is hovering:
    Code (csharp):
    1.  
    2.   private Rect SceneUIRect = new Rect(5,5,200,320);
    3.    private Vector3 MouseTilePosition;
    4.    private Event mouseAction;
    5.    void OnSceneGUI(){
    6.      //Only active when Editor is enabled (2D mode)
    7.      if(ViewMode == true && myTarget != null){
    8.        //Get Mouse 2D World Position
    9.        MouseTilePosition = Event.current.mousePosition;
    10.        MouseTilePosition.y = SceneView.currentDrawingSceneView.camera.pixelHeight - MouseTilePosition.y;
    11.        MouseTilePosition = SceneView.currentDrawingSceneView.camera.ScreenToWorldPoint(MouseTilePosition);
    12.  
    13.        //Get the Current Event and ask for Mouse clicks
    14.        mouseAction = Event.current;
    15.        if(mouseAction.type == EventType.MouseDown && Event.current.button == 0){ //Mouse Left
    16.          //Fix Position
    17.          MouseTilePosition.x += 64;
    18.          //Clamp the Position to be positive only!
    19.          MouseTilePosition.x = (MouseTilePosition.x < 0)?0:MouseTilePosition.x;
    20.          MouseTilePosition.y = (MouseTilePosition.y < 0)?0:MouseTilePosition.y;
    21.          MouseTilePosition.z = Mathf.Clamp(MouseTilePosition.z, 0, 1);
    22.          Debug.Log(MouseTilePosition.y);
    23.          //In Odd lines, reduce X by the half Tile Width
    24.          if((int)(MouseTilePosition.y/myTarget.TileSize.y)%2 == 1){ //Odd line 1,3,5,7...
    25.            MouseTilePosition.x -= myTarget.TileSize.x/2;
    26.          }
    27.          //Get the Tile Index from world Position
    28.          myTarget.TileIndex.x = (int)(MouseTilePosition.x/myTarget.TileSize.x);
    29.          myTarget.TileIndex.y = (int)(MouseTilePosition.y/myTarget.TileSize.y);
    30.          //Clamp the Indexes to be inside the mapsize only
    31.          myTarget.TileIndex.x = Mathf.Clamp(myTarget.TileIndex.x, 0, myTarget.Mapsize.x-1);
    32.          myTarget.TileIndex.y = Mathf.Clamp(myTarget.TileIndex.y, 0, myTarget.Mapsize.y-1);
    33.          //Unmark the last selected tile (if there is one), and mark the new selected one.
    34.          if(myTarget.GlobalTilemap != null){
    35.            if(myTarget.GlobalTilemap[(int)myTarget.LastTileIndex.y][(int)myTarget.LastTileIndex.x].TileObject != null)
    36.              myTarget.GlobalTilemap[(int)myTarget.LastTileIndex.y][(int)myTarget.LastTileIndex.x].TileObject.GetComponent<SpriteRenderer>().color = Color.white;
    37.            if(myTarget.GlobalTilemap[(int)myTarget.TileIndex.y][(int)myTarget.TileIndex.x].TileObject != null)
    38.              myTarget.GlobalTilemap[(int)myTarget.TileIndex.y][(int)myTarget.TileIndex.x].TileObject.GetComponent<SpriteRenderer>().color = Color.red;
    39.            //Set the last selected index
    40.            myTarget.LastTileIndex = myTarget.TileIndex;
    41.          }
    42.          //Eat mouse Event
    43.          mouseAction.Use();
    44.        }
    45.        else if(mouseAction.type == EventType.MouseDown && Event.current.button == 1){ //Mouse Right
    46.          mouseAction.Use();
    47.        }
    48.  
    49.        //Add SceneView Default UI
    50.        HandleUtility.AddDefaultControl(GUIUtility.GetControlID(FocusType.Passive));
    51.        HandleUtility.Repaint();
    52.  
    53.        //Add own UI
    54.        Handles.BeginGUI();
    55.        GUILayout.BeginArea(SceneUIRect);
    56.  
    57.        GUILayout.EndArea();
    58.        Handles.EndGUI();
    59.      }
    60.    }
    61.  
    And here is the Tilemap Code to this Editor Script
    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using UnityEngine.UI;
    4. using System;
    5. using System.Collections;
    6. using System.Collections.Generic;
    7.  
    8. public class Sc_IsoTiles_Tilemap : MonoBehaviour {
    9.  
    10.    [System.Serializable]
    11.    public class TilemapData{
    12.      public int TileID;
    13.      public float TileElevation;
    14.      public string TileSpritename;
    15.      public GameObject TileObject;
    16.    
    17.      public TilemapData(){
    18.        TileID = 0;
    19.        TileElevation = 0.0f;
    20.        TileSpritename = "Sprite_Tile_Basic";
    21.        TileObject = null;
    22.      }
    23.    }
    24.  
    25.    public List<List<TilemapData>> GlobalTilemap;
    26.    public GameObject BasicTileObject;
    27.    public Vector2 Mapsize;
    28.    public Vector2 TileSize;
    29.    public Vector2 TilemapSize;
    30.    [HideInInspector]
    31.    public Vector2 LastTileIndex, TileIndex = Vector2.zero;
    32.    [HideInInspector]
    33.    public int TileRealPixelheight;
    34.    private int IDrunthrough;
    35.    private bool Indent;
    36.  
    37.    void Start(){
    38.    }
    39.  
    40.    public void FillTilemap(){
    41.      IDrunthrough = 0;
    42.      Indent = false;
    43.      TileRealPixelheight = BasicTileObject.GetComponent<SpriteRenderer>().sprite.texture.height;
    44.      if(GlobalTilemap != null){
    45.        GlobalTilemap.Clear();
    46.      }
    47.      GlobalTilemap = new List<List<TilemapData>>();
    48.      for(int iy = 0; iy < (int)Mapsize.y; iy++){
    49.        GlobalTilemap.Add(new List<TilemapData>());
    50.        for(int ix = 0; ix < (int)Mapsize.x; ix++){
    51.          GlobalTilemap[iy].Add(new TilemapData());
    52.          GlobalTilemap[iy][ix].TileObject = (GameObject)Instantiate(BasicTileObject, Vector3.zero, Quaternion.Euler(0,0,0));
    53.          GlobalTilemap[iy][ix].TileObject.transform.parent = transform;
    54.          GlobalTilemap[iy][ix].TileObject.transform.name = "Tile #" + IDrunthrough + " [Basic] on YX-Pos [" + iy + "," + ix + "]";
    55.          GlobalTilemap[iy][ix].TileObject.transform.position = new Vector3(
    56.            (ix*TileSize.x) + ((Indent)?(TileSize.x/2):0),
    57.            (iy*TileSize.y),
    58.            iy*0.01f
    59.          );
    60.          if(GlobalTilemap[iy][ix].TileObject.transform.FindChild("Canvas") != null){
    61.            GlobalTilemap[iy][ix].TileObject.transform.FindChild("Canvas").FindChild("Text").GetComponent<Text>().text = "YX\n" + iy + "," + ix;
    62.          }
    63.        
    64.          IDrunthrough ++;
    65.        }
    66.        Indent = (Indent)?false:true;
    67.      }
    68.      TilemapSize.x = GlobalTilemap.Count;
    69.      TilemapSize.y = GlobalTilemap[0].Count;
    70.    }
    71.  
    72.    public void WhitenTilemap(){
    73.      if(GlobalTilemap != null){
    74.        TileRealPixelheight = BasicTileObject.GetComponent<SpriteRenderer>().sprite.texture.height;
    75.        TilemapSize.x = GlobalTilemap.Count;
    76.        TilemapSize.y = GlobalTilemap[0].Count;
    77.        for(int iy = 0; iy < (int)Mapsize.y; iy++){
    78.          for(int ix = 0; ix < (int)Mapsize.x; ix++){
    79.            GlobalTilemap[iy][ix].TileObject.GetComponent<SpriteRenderer>().color = Color.white;
    80.          }
    81.        }
    82.      }
    83.    }
    84.  
    85.    public void ClearTilemap(){
    86.      if(GlobalTilemap == null){
    87.        return;
    88.      }
    89.      GlobalTilemap.Clear();
    90.      for(int childs = transform.childCount-1; childs > -1; childs--){
    91.        if(transform.GetChild(childs) != null){
    92.          DestroyImmediate(transform.GetChild(childs).gameObject);
    93.        }
    94.      }
    95.    }
    96.  
    97.    public void CreateMap(){
    98.    
    99.    }
    100. }
    101.  
    So.. i´m working on this ******* Code for 2 Months now.. and can´t find a solution to calculate the Tilemap Position of a Tile..
    As you can see in the Screenshot above:
    The red Tile is selected - But the green Dot is the Mouse...

    I can´t get this to work and i seriously will give this up, when i can´t find a solution for this problem..

    So...
    Please.. i beg on you.. HELP ME :(

    How can i calculate the Tilemap Position to access the correct Tile of my Tilemap Array?


    Edit:
    Basic Sprite in the Attachment
     

    Attached Files:

    Last edited: Apr 5, 2016
  2. Polymorphik

    Polymorphik

    Joined:
    Jul 25, 2014
    Posts:
    599
    Have you tried to just raycast?
     
  3. Chaosgod_Esper

    Chaosgod_Esper

    Joined:
    Oct 25, 2012
    Posts:
    295
    the problem is not to get the world position...that is done and working..
    the problem is:
    how to get the tilemap[y][x] position from the world position..

    The Sprites itself don't hold any script or collider, they are just - sprites..
     
  4. eisenpony

    eisenpony

    Joined:
    May 8, 2015
    Posts:
    938
    How are you handling the fact that your tiles appear as diamonds from this perspective?
    I think these lines of code assume your tiles will be squares:
    Code (csharp):
    1. myTarget.TileIndex.x = (int)(MouseTilePosition.x/myTarget.TileSize.x);
    2. myTarget.TileIndex.y = (int)(MouseTilePosition.y/myTarget.TileSize.y);
     
  5. Chaosgod_Esper

    Chaosgod_Esper

    Joined:
    Oct 25, 2012
    Posts:
    295
    They.. don´t appear as diamonds.. These are Sprites (as mentioned above).. so.. they are DRAWN isometric..
    :)
     
  6. Pavlon

    Pavlon

    Joined:
    Apr 15, 2015
    Posts:
    191
    I think eisenpony is right you could read

    http://gamedevelopment.tutsplus.com...ds-a-primer-for-game-developers--gamedev-6511
    and
    http://clintbellanger.net/articles/isometric_math/

    but what you need basicly is

    Code (CSharp):
    1.         // screen is your mouse position it can be that you have to add some offset to it like
    2.         // screen.x + camera.x or screen.x + mapPosition.x and what ever
    3.  
    4.         map.x = (screen.x / TILE_WIDTH_HALF + screen.y / TILE_HEIGHT_HALF) /2;
    5.         map.y = (screen.y / TILE_HEIGHT_HALF -(screen.x / TILE_WIDTH_HALF)) /2;
     
  7. Chaosgod_Esper

    Chaosgod_Esper

    Joined:
    Oct 25, 2012
    Posts:
    295
    your two links are only tuts for diamond approach, but not for jagged/indent regular grid projection ;)

    Same for your snipped..
     
  8. Pavlon

    Pavlon

    Joined:
    Apr 15, 2015
    Posts:
    191
    Ok now i got what its all about i read about it some years ago how the dudes from age of empires did it

    they got a image like this

    isoTile.jpg

    every time the player click you transform your mouse position on to the image and get the color

    white would mean you are on the tile
    green = y+1
    purple = y+1 x+2
    and so on

    well thats the basic idea behind it
     
  9. Chaosgod_Esper

    Chaosgod_Esper

    Joined:
    Oct 25, 2012
    Posts:
    295
    Woah o.o
    never thought of such a technic

    will try that today
    *wish me luck*
     
  10. Chaosgod_Esper

    Chaosgod_Esper

    Joined:
    Oct 25, 2012
    Posts:
    295
    Wohooow!!
    Working! A bit stress on the gridsystem, but now it's running like a charm!
    See:


    Thank you guys :)
    I never had the idea to use GetPixel for such a Job xD
     
    Pavlon likes this.
unityunity