# Placing units on isometric map (2D)

I'm making a map editor for further RTS game (2D), something like the first StarCraft Editor. Terrain tiles will be a rhombuses. So I'll probably just make an 2D array with intigers, that corresponds proper tiles. Then, after creating the terrain, you'd probably like to add some units and structures to map (especially if you're making a scenario). I'm not sure how do I check if the unit can be placed somewhere. I decided to make units almost independent from terrain tiles like in StarCraft (1), so the units are not placed in any grid. I'll give a simple image:

As you can see, those green tiles represent a passable area (grass, let's say), and a blue one impassable (for example water). That stickman in a box is our unit. You can place it only in green area. That means the box can't go outside the green rhombuses.

I have some ideas how to achieve this, but I'm not sure which one would be the most optimal.

1) Since I work in Unity, I could add a collider to every tile. That will be very simple to do and will probably have terrible optimalisation in maps 256x256.

2) Math. I can calculate if any of those boxes crosses tile's borders. If so, I'll have to check if all those tiles are passable. It won't be that easy to programme (well, for me at least) and... yeah, here comes my dillema. Am I right that it would have much better optimalisation? Is it worth the effort?

What about saving this map? I can easily save the array with tiles, but how can I do it with units? Just save their positions or is there a better way to do it?

EDIT: I've tested the first idea (I've written script to create 256x256 map - that will be probably the biggest, and to move a camera). The map generates quite long (comparing to tiles without collider), but after that there isn't much difference in performance (it doesn't mean it won't cause problems when I add more features than moving a camera ;)). I can also attach colliders only to impassable tiles, not all. This should improve the performance even more. Still not sure if that's a good idea.

EDIT 2: I've just realised how bad my idea was. Let me visualise this: So if you consider not the whole rectangle, but only a circle, it's not only easier to implement, but also more reasonable. You can now convert rhombus' vertices' position from isometric to cartesian like Bálint said:

CartX = ( 2 * IsoY + IsoX) / 2
CartY = ( 2 * IsoY - IsoX) / 2


You can also do it with circle's center point. Radius is equal to half of square (rhombus) side length OR sqrt(2) * square side length (when square is inscribed in circle).

So now I have a square grid and a circle. How can I check if all squares that this circle lays on are passable? What's the most optimal way to do it?

One big thing about optimization is that you should avoid doing it until you're sure you have a problem, and even then only after measuring to see where the problem actually is. Static colliders in Unity are generally pretty efficient so you probably will have less of a problem than you think.

All that being said, this is a question and answer site and you asked a question, so lets get to the answering! :)

Your best bet here, since you only need to do the check on the unit currently being moved/placed, is probably to use the collider method. If you're anxious about the number of colliders, what I would do is only put colliders on impassable tiles (unless you have need of knowing what kind of tile each unit touches) and then on placement/movement do a quick Physics.OverlapBox based on the unit's footprint (which could be different than the bounds of the sprite for that pseudo-3d look) to see what colliders are being hit and if the placement is valid. As an added bonus if you only put colliders on places where the units cannot be (or put all no-place colliders on the same layer and only check against that) you can skip the identifying the tile step and just go straight to collide = no placement. Not only that, but it will also work for any other non-tile things you think need to block placement, which is a handy bonus!

As some information you may find useful, when I had to do a lot of performance optimization I found static colliders only really cost when checks need to be made against them, which is primarily when dealing with nearby moving colliders, physics checks, and raycasts. A situation like what is listed above will be trivial compared to a situation with hundreds or thousands of moving colliders needing to have physics, collision, and response applied every physics timestep.

An exercise that would be worth doing would be trying the collision method you mentioned first before doing what I listed above. This will give you an actual worst case cost by looking at the profiler (or just feeling it out) which will be more informative than any stranger on the internet can be about where bottlenecks are or aren't in your game.

Of course even with negligible performance gain, Side benefits might still make various performance adaptations desirable, but that's up to you as the creator. There's a constant lure for engineers to make things leaner and faster (heck I've had to resist the urge to answer with a couple mathematical solutions which would be more difficult to implement but could skip the concept of colliding entirely) but it's important to know when you can go with the simple approach so you can spend your time on the more important bits. Good luck!

There's a way to convert isometric coordinates to cartesian ones:

x = (2 * mouseY + mouseX) / 2;
y = (2 * mouseY - mouseX) / 2;


Get the position using this formula, floor the values then check if the tile at that pos is walkable or not.

This is probably the fastest method, as it doesn't require any type of collision

• Well, I'd have to check if the line segments of my rectangle doesn't cross the rhombus ones. Of course I can do it, but it won't be that simple to do. Commented Jan 9, 2017 at 22:35
• I thought about this method a bit and it's actually much easier than I realised. I'll update my question with new idea. Useful formula anyways :) Commented Jan 10, 2017 at 14:05