Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Tile Coordinates Versus World Coordinates

Discussion in '2D' started by KrisSchnee, Mar 19, 2014.

  1. KrisSchnee

    KrisSchnee

    Joined:
    Mar 9, 2014
    Posts:
    15
    I'm coming from a background of making a tile-based game in Python, and very new to Unity, and having trouble handling the notion of character coordinates.

    In trying to port from Python: I've got a world of (say) 50x50 tiles. 2D. Turn-based, characters always on exactly one tile. I'm storing tile coordinates on scripts, and placing the associated sprites by attaching those scripts to Sprites which have a Transform property with coordinates. So I've got to keep track of the "tile coordinates" that tell me that the hero is standing on the forest tile at (42,3), and the "world coordinates" that tells Unity to draw the sprite at actual world coordinates of (84,6) or whatever, based on the tile size. Any smooth motion between tiles will have to be done by some tweening script or lerp function to say "gradually change the drawing coords, and when you're done, change the actual tile coords".

    Any advice on whether this double set of coordinates is a good idea? Or should I be using the Unity transform coords exclusively and truncating values or something whenever I need to know what tile a character is on?
     
  2. Invertex

    Invertex

    Joined:
    Nov 7, 2013
    Posts:
    1,539
    It seems like you're relying on a purely programming mindset/approach, instead of taking advantage of what Unity offers you in terms of optimizations and simpler approaches through better tools.

    Instead of storing all these coordinates and looking them up, or having the tiles placed based on these, you can simply create 1 prefab tile of each type, and place them in your scene however you'd like, using your movement Snap settings to keep them aligned as you Duplicate>Move copies.

    Set your Pixels to Units on your sprites to the resolution of individual tile sprites. This way, 1 tile sprite will equal 1 Unity Unit, keeping your math simple.

    There are various extremely simple ways to check which type of tile you're on or are surrounding you, raycasts or triggers being the simplest.

    Mathf.Lerp is what you want for the movement then, no need for a tween script, just use it right in your player movement.
    http://docs.unity3d.com/Documentation/ScriptReference/Mathf.Lerp.html

    You won't need scripts on your tiles this way. Though I'm not entirely sure what you want to achieve. What do you mean change the tile coords?
     
  3. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    I wouldn't recommend working that way; trying to mess with raycasting and triggers ends up being overly complex and inefficient. You're correct to use tile coordinates, since it simplifies a lot of things. Don't have scripts on every tile though. I'd suggest using an array to store the world, and do all movement etc. based on that. Unity by itself isn't really set up to deal with tile-based worlds, so you need to create a framework...have a look at SpriteTile if you want a system that's already done.

    --Eric
     
  4. KrisSchnee

    KrisSchnee

    Joined:
    Mar 9, 2014
    Posts:
    15
    That's what I was thinking, since I'm used to the linear approach of Python. Also, Unity is pretty far from the "model/view/controller" style of program design. Later I'll need to work out using DontDestroyOnLoad to keep my world safe when transitioning to battles, and I guess, pause all gameplay during a shop menu by using a line like "def Update: if not in_a_menu: do stuff".

    I mean, right now there's a little guy that moves by one tile N/S/E/W when you hit the arrow keys. So my code calculates what tile you're trying to reach (eg. west of (10,10) is (9,10)), then asks "is that within the world size, and is the tile passable?", then (1) changes the character's tile coords to (9,10) and (2) changes their parent object's Transform coords to whatever the equivalent is. (Hmm, yeah, a tile definitely should be 1 unit for simplicity.) Any lerping/tweening would be purely to make the sprite visibly move to the next tile instead of teleporting, and would not affect the tile it's officially on at any moment. Lerp is probably adequate.

    Looks like for 2D, there's a function (Camera.ScreenToWorldPoint) that can easily tell me that if the user clicked on pixel (500,400), that converts to tile (x,y), so that's good and doesn't require explicit raycasting (though that's probably what it's doing). I currently have the big main script storing a 2D array of Tiles, each of which has a TileData script containing info like the name, health, and building on that tile. So... would it be better to have another 2D array of tile names, another array of tile health, &c, all stored in the big main script? That approach seems like it's not very object-oriented. I need to store that info somewhere so I can do things like "have a monster damage the tile" or "give a combat bonus if a castle is nearby". I'm already using a second 2D array of Structures which are sprites in front of the Tiles, just to show buildings, and I'm not happy about that because I'll probably need a third layer just to highlight a set of Tiles to indicate movement ranges.

    Someone's tentatively offering to make a 3D model for me for their portfolio's sake, so I'm tempted to try 3D eventually... but not before getting a 2D version working! Same artist keeps cringing at my taste in toon-styled assets on the Asset Store. :)
     
    Last edited: Mar 19, 2014