- Home /
2D TileMap with each tile as a separate object
I'm currently working on a small project that's based on 2D tiles. My main problem now is figuring out how to have each tile have different properties (movement point cost etc.) that would be revealed in a tooltip on mouse-over. I've found some tutorials that deal with this rogue-like concept but they're all based on randomly generated maps which I don't plan to use.
My current solution would be to have each non-cosmetic tile as a separate object with collision box so it can be detected with OnMouseOver and then the scripted properties would be shown on a tooltip. Each time player would move a script would check the properties of the tile and act accordingly.
At my current game resolution/tile size that's ~225 tiles/objects onscreen in a busy scene, but usually less since walls/decorations would be grouped up as meshes. The off-screen tiles would be culled. But as I've read Unity has problems handling many objects at once but I'm not sure how many on-screen tiles would be too much, performance wise.
So I'd like some advice on how to deal with tile based game where most of them aren't just cosmetic and should affect the player in one or more ways (with tooltips OnMouseOver) without killing the performance and not employing randomly generated maps.
Thanks.
Answer by toddisarockstar · Jun 23, 2017 at 08:32 PM
Check out the similar example i gave here to create an array of arrays to represent coordinates:
you could set up your tile/mouseover positions in space to correlate with arrays of info. i would recommend making the first tile in your scene start at postition 0,0 then make the tile/grid positions at even number positions up and right from that so that they are all positive. Then when you get your mouseover position, it can simply be rounded off and directly used to get info from an array based on the two coordinates. this method should is super proficient too. let me know if you have any questions about it!
Thanks for the recommendation, I'll try it tomorrow.
Ok so I used your script and it seems to generate the coordinate array. By default their values are 0 and assigning values manually also works. So far so good.
I'm very new to C# so this is all new to me. Anyway this code displays mouse's location in world coordinates (they still have a decimal point for some reason, $$anonymous$$athf.Round properly removes the decimal point in the next code part though).
void OnGUI()
{
Vector2 p = new Vector2();
Camera c = Camera.main;
p = c.ScreenToWorldPoint(new Vector2($$anonymous$$athf.Round(Input.mousePosition.x), $$anonymous$$athf.Round(Input.mousePosition.y)));
GUILayout.BeginArea(new Rect(40, 400, 250, 120));
GUILayout.Label("World position: " + p);
GUILayout.EndArea();
}
This part stores mouse x and y world coords in separate variables on key press. For some reason the Debug.Log is called twice but at least I get int values, no decimals.
if (Input.Get$$anonymous$$eyDown($$anonymous$$eyCode.$$anonymous$$ouse0))
{
int mouseInfoX = $$anonymous$$athf.RoundToInt(p.x);
int mouseInfoY = $$anonymous$$athf.RoundToInt(p.y);
Debug.Log("X: " + mouseInfoX + "Y: " + mouseInfoY);
}
I tried figuring out how to compare the mouse location (in world) with the array (with foreach etc.) but I'm obviously missing something so nothing worked. So now I need advice how to compare the array with mouse coordinates int values.
Next step would be some auto-assignment of array properties. It would be quite laborious to manually edit array each time I make a map. I'm currently using Tiled and Tiled2Unity for tile maps and the map is exported as a .xml file with the tile/layer properties. There should be a way to combine the Tiled2Unity mesh (visual part) with Tiled xml (data part).
OnGUI can be called multiple times per frame so it's bad using Input.Get$$anonymous$$ey and similar in it as these will fire twice as you already noticed. Ins$$anonymous$$d, use Events.
Don't use $$anonymous$$athf.Rount to get your cursor tile position. Use $$anonymous$$athf.Floor ins$$anonymous$$d.
Vector3 cursorPos = YourCamera.ScreenToWorldPoint(Input.mousePosition);
coords_cursor = new Vector2( $$anonymous$$athf.FloorToInt(cursorPos.x), $$anonymous$$athf.FloorToInt(cursorPos.y) );
There is cvertainly a way to read and convert Tiled's format, after all that's what Tiled2Unity does, but it involves diving deep into the code so if you are a beginner be prepared for quite a task at hand. That's one of the reasons why I commonly write my own level editors.
i
Thank you, removed the mouse function from OnGui, will learn more about events.
FloorToInt is indeed better, turns out rounding (up) would result in 1 tile offset, didn't notice that at first.
Yeah, the xml produced by Tiled is quite readable even for me but using it is something else. Of course I'm not the first one to try something like this so I'm slowly gathering tips/methods for my grid/tile based game.