Implementing a world map in Unity

I’m currently trying to implement an interactive world map where you can click on any country, similar to plague inc. and other strategy games. I have thought of just using a texture and adding colliders manually for each country, then testing for OnMouseEnter. However this feels very repetitive (150+ countries).

Is there any other, cleaner way to implement this?

That game has a few clickable countries though…
I would do it manually if its a mobile game, just with box colliders, but if really need precision without colliders maybe using a coordinate system, since is a real map.

I wouldn’t use box colliders for this. It’ll be incredibly hard to get things like borders between countries accurate, and you’ll need a huge number of colliders.

I would have a texture where each country is mapped to a number value (which will be visible as a colour). When someone clicks on the map, look up the UV coordinate of where they clicked, grab the texture value (ie: colour) at that pixel, and look up the country that value is mapped to. You’ll get pixel perfect click detection. You’ll still need to make the look up texture in your image editing software, but I suspect that’ll be a bit easier than placing colliders.

Since there are only 195 countries in the world (according to Google, at least) you can do this all with just an 8 bit texture. Alternatively, if there’s other data which would also be mapped well in this fashion (continents? population density? altitude? average temperature?) you could put those things in the other bits of an RGB(A) texture.

Regardless of colour format, you probably want to make sure the texture is uncompressed from creation to import. Compression can change your colour values a bit, and while it’s usually not noticeable to the human eye it could still interfere with looking up mapped values. Also use hard edged brushes / regions when making the map texture so that the colours don’t blend into each other, which will make your edges less accurate. It’s ok if the image has ugly, aliased edges - it’s about unambiguous mapping, not looking pretty.

2 Likes

You’ll need some way to test which country is which, no matter what you do. For example, you could store an offscreen bitmap where each country is colored with unique (indexed?) color. Then you can save some space in memory by storing it as a sparse map in custom format. But that would incur development costs.

Another possibility is to design polygonal map within a 3d editor, and either assign an unique material, or unique object name for each continent.

But either way you’ll have to mark every country one way or another. 165 isn’t a whole lot of countries. though.

1 Like

You can also use country code ex: alpha 3 code as a color in your country lookup texture.

Box colliders aren’t going to fly, because countries are not square and are often concave. For example, if you try to boxcollide USA, then Canada, Russia and portion of Mexico will be caught in the box. It is too imprecise to be useful.

1 Like

Another option is to split up your map into separate meshes, one per country. They will all have the same material and just different UVs, so if you set things up correctly Unity should batch them back together for little to no performance impact. Then you can just check which country is associated with the mesh which was clicked on, via a list of KeyValuePair<GameObject, Country>, or by having a component attached to each, or something similar.

Having the mesh pre-split also lets you do things like have mouse-over effects on countries or various visual effects a bit more easily, as you already have unique geometry for each one.

Might also use a bit less memory than an uncompressed texture of an equivalent resolution, though I doubt that would be of concern.

Thanks for the reply. I’ve already implemented the texture/color lookup but I’m still unclear on how to map color to countries. Could it be just a simple serialized color-country(ScriptableObject) dictionary or am I missing something?

That’s pretty much what I’d do. If you use the Colour type Unity will hopefully even give you a colour picker widget to use.