HELP!! Great problem with Iso Grid -> Tilemap

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:

  private Rect SceneUIRect = new Rect(5,5,200,320);
   private Vector3 MouseTilePosition;
   private Event mouseAction;
   void OnSceneGUI(){
     //Only active when Editor is enabled (2D mode)
     if(ViewMode == true && myTarget != null){
       //Get Mouse 2D World Position
       MouseTilePosition = Event.current.mousePosition;
       MouseTilePosition.y = SceneView.currentDrawingSceneView.camera.pixelHeight - MouseTilePosition.y;
       MouseTilePosition = SceneView.currentDrawingSceneView.camera.ScreenToWorldPoint(MouseTilePosition);
  
       //Get the Current Event and ask for Mouse clicks
       mouseAction = Event.current;
       if(mouseAction.type == EventType.MouseDown && Event.current.button == 0){ //Mouse Left
         //Fix Position
         MouseTilePosition.x += 64;
         //Clamp the Position to be positive only!
         MouseTilePosition.x = (MouseTilePosition.x < 0)?0:MouseTilePosition.x;
         MouseTilePosition.y = (MouseTilePosition.y < 0)?0:MouseTilePosition.y;
         MouseTilePosition.z = Mathf.Clamp(MouseTilePosition.z, 0, 1);
         Debug.Log(MouseTilePosition.y);
         //In Odd lines, reduce X by the half Tile Width
         if((int)(MouseTilePosition.y/myTarget.TileSize.y)%2 == 1){ //Odd line 1,3,5,7...
           MouseTilePosition.x -= myTarget.TileSize.x/2;
         }
         //Get the Tile Index from world Position
         myTarget.TileIndex.x = (int)(MouseTilePosition.x/myTarget.TileSize.x);
         myTarget.TileIndex.y = (int)(MouseTilePosition.y/myTarget.TileSize.y);
         //Clamp the Indexes to be inside the mapsize only
         myTarget.TileIndex.x = Mathf.Clamp(myTarget.TileIndex.x, 0, myTarget.Mapsize.x-1);
         myTarget.TileIndex.y = Mathf.Clamp(myTarget.TileIndex.y, 0, myTarget.Mapsize.y-1);
         //Unmark the last selected tile (if there is one), and mark the new selected one.
         if(myTarget.GlobalTilemap != null){
           if(myTarget.GlobalTilemap[(int)myTarget.LastTileIndex.y][(int)myTarget.LastTileIndex.x].TileObject != null)
             myTarget.GlobalTilemap[(int)myTarget.LastTileIndex.y][(int)myTarget.LastTileIndex.x].TileObject.GetComponent<SpriteRenderer>().color = Color.white;
           if(myTarget.GlobalTilemap[(int)myTarget.TileIndex.y][(int)myTarget.TileIndex.x].TileObject != null)
             myTarget.GlobalTilemap[(int)myTarget.TileIndex.y][(int)myTarget.TileIndex.x].TileObject.GetComponent<SpriteRenderer>().color = Color.red;
           //Set the last selected index
           myTarget.LastTileIndex = myTarget.TileIndex;
         }
         //Eat mouse Event
         mouseAction.Use();
       }
       else if(mouseAction.type == EventType.MouseDown && Event.current.button == 1){ //Mouse Right
         mouseAction.Use();
       }
  
       //Add SceneView Default UI
       HandleUtility.AddDefaultControl(GUIUtility.GetControlID(FocusType.Passive));
       HandleUtility.Repaint();
  
       //Add own UI
       Handles.BeginGUI();
       GUILayout.BeginArea(SceneUIRect);
  
       GUILayout.EndArea();
       Handles.EndGUI();
     }
   }

And here is the Tilemap Code to this Editor Script

using UnityEngine;
using UnityEngine.UI;
using System;
using System.Collections;
using System.Collections.Generic;

public class Sc_IsoTiles_Tilemap : MonoBehaviour {
 
   [System.Serializable]
   public class TilemapData{
     public int TileID;
     public float TileElevation;
     public string TileSpritename;
     public GameObject TileObject;
   
     public TilemapData(){
       TileID = 0;
       TileElevation = 0.0f;
       TileSpritename = "Sprite_Tile_Basic";
       TileObject = null;
     }
   }
 
   public List<List<TilemapData>> GlobalTilemap;
   public GameObject BasicTileObject;
   public Vector2 Mapsize;
   public Vector2 TileSize;
   public Vector2 TilemapSize;
   [HideInInspector]
   public Vector2 LastTileIndex, TileIndex = Vector2.zero;
   [HideInInspector]
   public int TileRealPixelheight;
   private int IDrunthrough;
   private bool Indent;
 
   void Start(){
   }
 
   public void FillTilemap(){
     IDrunthrough = 0;
     Indent = false;
     TileRealPixelheight = BasicTileObject.GetComponent<SpriteRenderer>().sprite.texture.height;
     if(GlobalTilemap != null){
       GlobalTilemap.Clear();
     }
     GlobalTilemap = new List<List<TilemapData>>();
     for(int iy = 0; iy < (int)Mapsize.y; iy++){
       GlobalTilemap.Add(new List<TilemapData>());
       for(int ix = 0; ix < (int)Mapsize.x; ix++){
         GlobalTilemap[iy].Add(new TilemapData());
         GlobalTilemap[iy][ix].TileObject = (GameObject)Instantiate(BasicTileObject, Vector3.zero, Quaternion.Euler(0,0,0));
         GlobalTilemap[iy][ix].TileObject.transform.parent = transform;
         GlobalTilemap[iy][ix].TileObject.transform.name = "Tile #" + IDrunthrough + " [Basic] on YX-Pos [" + iy + "," + ix + "]";
         GlobalTilemap[iy][ix].TileObject.transform.position = new Vector3(
           (ix*TileSize.x) + ((Indent)?(TileSize.x/2):0),
           (iy*TileSize.y),
           iy*0.01f
         );
         if(GlobalTilemap[iy][ix].TileObject.transform.FindChild("Canvas") != null){
           GlobalTilemap[iy][ix].TileObject.transform.FindChild("Canvas").FindChild("Text").GetComponent<Text>().text = "YX\n" + iy + "," + ix;
         }
       
         IDrunthrough ++;
       }
       Indent = (Indent)?false:true;
     }
     TilemapSize.x = GlobalTilemap.Count;
     TilemapSize.y = GlobalTilemap[0].Count;
   }
 
   public void WhitenTilemap(){
     if(GlobalTilemap != null){
       TileRealPixelheight = BasicTileObject.GetComponent<SpriteRenderer>().sprite.texture.height;
       TilemapSize.x = GlobalTilemap.Count;
       TilemapSize.y = GlobalTilemap[0].Count;
       for(int iy = 0; iy < (int)Mapsize.y; iy++){
         for(int ix = 0; ix < (int)Mapsize.x; ix++){
           GlobalTilemap[iy][ix].TileObject.GetComponent<SpriteRenderer>().color = Color.white;
         }
       }
     }
   }
 
   public void ClearTilemap(){
     if(GlobalTilemap == null){
       return;
     }
     GlobalTilemap.Clear();
     for(int childs = transform.childCount-1; childs > -1; childs--){
       if(transform.GetChild(childs) != null){
         DestroyImmediate(transform.GetChild(childs).gameObject);
       }
     }
   }
 
   public void CreateMap(){
   
   }
}

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 :frowning:

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

Edit:
Basic Sprite in the Attachment

2582547--180587--Sprite_Tile_Basic.png

Have you tried to just raycast?

the problem is not to get the world position…that is done and working…
the problem is:
how to get the tilemap[y][×] position from the world position…

The Sprites itself don’t hold any script or collider, they are just - sprites…

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:

myTarget.TileIndex.x = (int)(MouseTilePosition.x/myTarget.TileSize.x);
myTarget.TileIndex.y = (int)(MouseTilePosition.y/myTarget.TileSize.y);

They… don´t appear as diamonds… These are Sprites (as mentioned above)… so… they are DRAWN isometric…
:slight_smile:

I think eisenpony is right you could read

and
http://clintbellanger.net/articles/isometric_math/

but what you need basicly is

        // screen is your mouse position it can be that you have to add some offset to it like
        // screen.x + camera.x or screen.x + mapPosition.x and what ever

        map.x = (screen.x / TILE_WIDTH_HALF + screen.y / TILE_HEIGHT_HALF) /2;
        map.y = (screen.y / TILE_HEIGHT_HALF -(screen.x / TILE_WIDTH_HALF)) /2;

your two links are only tuts for diamond approach, but not for jagged/indent regular grid projection :wink:

Same for your snipped…

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

2583284--180596--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

Woah o.o
never thought of such a technic

will try that today
wish me luck

Wohooow!!
Working! A bit stress on the gridsystem, but now it’s running like a charm!
See:

Thank you guys :slight_smile:
I never had the idea to use GetPixel for such a Job xD

1 Like