Tiled Maps using Mapbox Unity SDK

I wrote this draft months ago but realizing I won’t be able to finish it, I just decided to post it as is. I hope it’ll at least explain the idea. I’m also thinking about going back to square tiled version of this soon and finish it properly this time

I kept saying I’ll blog this for so long but finally, here it is; creating tiled maps using Mapbox and Unity3d! Well at least I’m starting, we’ll see how it’ll turn out.

First of all, a little bit of background;
It actually all started with some 2d map experiments I did like 8 months ago. I was trying to create a 2d fantasy theme map and after checking some examples online, I decided to go with a hexagon tile based map. I always loved hexagons to begin with but on the technical side, I thought it would also help to place visuals/models to represent map entities.

If you check the forests or water, you probably can notice the hexagon grid. I still love the style but it was pretty hard to find/create art assets for this so it ended up kinda… ugly? I didn’t get too much attention either as it was rather unpolished, more like a proof of concept at the time. I’m pretty sure it could have been soo much better with a 2d artist.

Then one night, while searching for art assets, I stumbled upon a beautiful package in Unity asset store with beautiful toonish hexagon tiles. With a little change in the code, I created this;

This one got quite popular, probably mostly due to beautiful art assets. It’s just a lot more fun and interesting to look. Also this time I spent a little more time to polish it with some animations and units moving around.

But shortly, the idea was to turn a regular vector map into a tiled map;

It’s actually quite a fun real map and I believe it can be useful for a lot of different type of applications; PokemonGo type of mobile games, Civilization type of desktop games or mobile location based messaging apps.

About this post

Now I want to clearly note that  I won’t share any code in this post. This was an experimental project for me and my goal was to see what I can do (and collect some internet points) so my implementation was rather rough, buggy, pretty unoptimized. I will, however, try to explain who process so you can do better!

So how do we start?

I started with exploring the vector data and try to see what we can get out of that one first. All vector layers aren’t available on all levels and their detail level varies quite a bit as well so I had to try a few settings until I created this;

This strange looking map will be our starting point. Yellow textured part here is “land”, pink is “mountain”, green is “forests” and white is “grass”.
Actually I had to do some tricky stuff to achieve some of these layers. Mapbox vector data doesn’t have “land” for example, or mountains. To be able to create them, I used “contour” layer (see https://www.mapbox.com/vector-tiles/mapbox-terrain/#contour). In case you’re not familiar with contour lines, this is what they look like;

Now our goal is to find the polygons/heights we want to define as “land” and “mountain”.

Land is easy, elevation=0 should be land, right?

Mountains though a little bit trickier as contour layer uses different intervals on each zoom level so this value kinda depends on it. For example, “elevation 200” would work for all levels above 10 but it won’t work for zoom level 9 as it uses 500 meter intervals and there won’t be “elevation 200” in that level.

I created my demos using zoom level 10 as it felt the best for big areas, and at z10 I used;

  • Contour layer elevation=0 for land
  • Landcover layer class=grass for grass
  • Landuse layer for forests (I didn’t filter by type/class as landuses are mostly national parks at this level)
  • Contour layer elevation=200 for mountains

I also ordered them bottom to top so the latter will be on top of former and it all results in that top down shot above.

So now we have the polygons, what’s next?

Rasterization

Wikipedia defines rasterization as; “the task of taking an image described in a vector graphics format (shapes) and converting it into a raster image (pixels or dots).”

Exactly what we’re looking for!
We have the polygons so now what we have to do is (basically) to rasterize these polygons, which will yield us a set of tiles, and visualize those tiles.

Now it gets a little more implementation specific, I’ll try to describe how I did it but I’m pretty sure there might be better approaches as well.

We already know these polygons generally overlap and then we’ll also want to play with neighbourhood relations in between tiles (i.e. roads or special models for city by water/mountain) so instead of creating tiles one by one (as they are created), I decided to pass them all to a controller class first. And only after it’s all finished, I process them and create visuals in one final loop.

Also, I tried not to change SDK code at all and built this on top of it as a separate layer. Having whole SDK and a new layer on top of it means an unoptimized structure but it’s easy and faster to develop.

Mapbox Unity SDK Components

If you’re familiar with the Mapbox Unity SDK, you know it’s rather easy to create polygons from features. Most demos and example do much more than creating the polygon so it might be easy to overlook.

This is my “land” layer in the SDK side for example. It uses custom styling and “contour” layer name. Then filters by the “ele” property and takes the ones with value 0 (coastline).

PolygonMeshModifier creates the polygon, AddToHexMap modifier adds it to our other layer, tiled map controller. And finally DisableMeshRenderer hides the original polygon.

And actually, depending on your rasterization technique, you might not need the PolygonMeshModifier at all. I used it because if I remember correct, I was using triangles for rasterization and needed the triangulation inside PolygonMeshModifier.

So shortly, whole idea here is to pass features to the TiledMapController and do everything tiled there. We’re using SDK only to parse, categorize, filter etc the features.

AddToHexMap here is a very simple custom game object modifier and all it does is passing a few values to the tiled map controller, including feature data, tile, layer (land, forest etc) and type of data (point/line/polygon). My implementation didn’t include dynamic tile loading so it didn’t destroy objects. When you need that though, AddToHexMap can send signal to controller for the destruction of features and tiles as well.

Visualization

This way tiled map controller will get all features, layers and types. Then I rasterized polygons to find the list of tiles covering given polygon and kept them in a Dictionary<Vector2, TileFeature> where the first parameter is the tile position and second one is an enum corresponding to the layer name (land/forest/mountain etc). There’s a few advantages of this; first of all, tile coordinates are rather easy to calculate and Dictionary provides O(1) read complexity in that very common case. Second, it helps to layer things like using forest over land. Vector layer execution order should also be enough but this is nice to have. Third, again it helps with some basic tile type relations; i.e. if current value is forest and you get mountain, you can switch to a custom type like mountain forests.

Earlier vector roads over hexagon tiles
Tile based roads

I kept and processed roads separately as they were kinda afterthought in my case. I’m sure you can process them in same pipeline but might require a little more effort.

At this point our dictionary should be full of tiles. Now we’ll wait for the AbstractMap.MapVisualizer.OnMapVisualizerStateChanged event, which means all features are processed and you can start creating your tile visuals.
For visuals, I used POLYGON MINI - Fantasy Pack by Synty Studios (https://assetstore.unity.com/packages/3d/props/exterior/polygon-mini-fantasy-pack-96800). Created bunch of variations for each layer type and saved them in lists. Then went through the tile dictionary and picked a random tile from the list corresponding to tile TileFeature.

Final Words

Looking back, the most difficult part of this project was the rasterization algorithm which I shamelessly avoided in this post. I only had a subpar rasterization implementation but it worked so I didn’t bother to improve it for now. I’m sure there are much better hex/square tile rasterization formulas online though.

I think it covers the main idea behind tiled maps. I really love this project and will definitely get back to it at some point.

Please let me know if you have any questions or if you like it or not!

Mapbox Unity SDK Terraced terrain style

Lines and polygons in Mapbox Unity SDK

It has been…..8 months since that last post?? So 8 months since I started working at Mapbox. I can’t believe it, time sure flies. That was an extremely busy 8 months and I, being a lazy blogger, couldn’t blog at all. But I’ll try to change that, I think I even found an awesome subject for this first blog post; how we treat line and polygons in Mapbox Unity SDK. And it’s not only that, I’ll try to explain it over contour lines data showing how to recreate meshes for two different styles; scifi contour lines and terraced terrain style with this.

Mapbox Unity SDK Scifi terrain style
Scifi contour lines

We can classify geometry types in Mapbox vector api in three groups; points (pois, labels etc), lines (roads, borders etc) and polygons (buildings, landuse, water etc). We’ll leave points aside for this post. They are quite interesting as well so might come back to that in another post though.

And actually let me just take a small step back and describe how these types are used. So we have this vector data right? It’s all hierarchical so you can visualizer it as xml or json in your head.

Root of the vector data contains a list of layers; like building layer and road layer. They have such names but there’s nothing else indicating what kind of layer it is and how it should be visualized so it’s all abstract. Inside these layers, we have “features”, individual buildings or road segments and these feature actually have lots of meta data with them, most importantly (for this blog post) the “GeometryType” of that feature. So shortly, we have bunch of layers containing features with “GeometryType” property.

You probably noticed how I’m emphasizing “GeometryType” right? That’s mainly because we don’t use this property anywhere at all. Sounds weird huh? Maybe a little, and we probably will use it at some point for certain special cases but one of our main goals with Unity SDK is to make it flexible so there are no restrictions or anything on what to use. So for example, you can render building data as lines to create walls or lakes data as lines to create shore.

mapbox unity sdk terraced terrain game shot
Just a random shot to break the wall of text

Another interesting thing to note here is that, GeometryType is just a property under feature. Other than that, both line and polygon features (even points actually) uses same structure to keep their data; list of vertices. Only difference between two is that polygon vertex list is closed (first and last vertices are same) and line vertex list is open.

Now let me show you the difference data&modifier makes. I’ll use the terraced terrain demo in the latest version of SDK and chamge some properties and stuff there. You can create similar stuff using that as well.

contour line mapbox sdk

What you see in that image is just one contour line feature, at the corner of a tile. So this tile has that a little elevation at the south west corner. That polygon is created using a mesh factory with “mapbox.mapbox-terrain-v2” source id (you can find its detailes here;  Vector Data page), which comes as default in that demo scene. I’m saying that because v2 of that api has contour lines defined as polygons. And then I used PolygonMeshModifier to visualize it as a polygon. Nothing fancy so far. But for example, what happens when you use line mesh modifier on a polygon?

contour line mapbox sdk

If you can ignore how ugly it looks on sharp edges, you’ll see it creates an outline. It’s kind of useless for contour I guess…. but maybe not. It’s all up to your imagination in the end. But as I mentioned before, you can create borders of a lake or a park with this. And I promise I’ll improve that corners thing soon! 🙂

Now I’ll switch source id to “mapbox.mapbox-terrain-v1”. So this version has contour feature as lines. It doesn’t mean much though, just that first&last vertices in the list are not the same. But let’s have a look at how both modifiers work with that;

contour line mapbox sdk

This is the v1 data with line mesh modifier. Important thing to note here, since v2 actually filled the whole space adding an extra vertex at the bottom left corner so it looks like a big triangular area. But real contour line is actually just this line, and without a need to fill empty space to create a polygon, we get a nice clean contour line using this.

Finally, what happens when you use polygon mesh modifier on a line;

contour line mapbox sdk

Yep. It’s not surprising I guess but polygon modifier normally created a polygon connecting the first and last vertices, and ended up with this totally wrong output. I think it’s safe to say that this is flat out wrong as I can’t think of a single use case.

To summarize it quickly, we have two geometry types (line and polygon) and two core mesh modifiers (line mesh and polygon mesh) which you can use in bunch of different ways to create different outputs.

Admittedly system doesn’t help you with these either , like saying that it would be better to use polygon on buildings etc. We’ll look into that soon and try to add some guidance&help beyond the demo scenes though.

 

Finally, I’ll show you the mesh gen structure to create those scifi and terrace styles using the brand new node editor I’m working on these days!

contour line mapbox sdk
This is the terraced terrain style, actually what you already have in that demo scene. Still wanted to post this so you can see how it actually looks on a graph and understand that demo better. This is using “mapbox.mapbox-terrain-v2”.

And for the scifi style;

contour line mapbox sdk

It’s almost exactly same really, just have a line mesh modifier instead of a polygon mesh modifier. And “Scifi Mesh Factory” there is using “mapbox.mapbox-terrain-v1” of course. We probably will also have a walkthrough/tutorial for this at Mapbox blog soon as well.

And this is it. Hope you helps you understand what’s going on behind the scenes a little better. Let me know if you have any questions or feedback about this blog post or SDK in general.

Cheers,
Baran

mapbox unity3d sdk openstreetmap mesh generation

New job, new project, new horizons

I know it has been a while since the last update on MapzenGo, sorry about that. I had lots of stuff going on and couldn’t find time to blog in that rush. Well actually title says it all right? MapzenGo project landed me a new awesome job at Mapbox and now I’ll be doing pretty much the same thing, map/city generation in Unity for them! OK maybe not New Horizons cool but it’s still pretty fucking cool, eh?

Mapbox is a huge custom map provider and they’ve been one of the top player in the scene for years. They have some awesome terrain (height), vector, satellite imagery APIs and most of their project are open source and hosted on Github! Now they (well it’s “we” now I guess) are going into gaming scene and started this Mapbox SDK for Unity3D project a short while ago. Aaannnd before you ask, yes, this SDK will be open source after the launch as well!

So that’s pretty much the whole story I guess, let’s try this for the rest;

-What will you be doing there?
I’ll mostly do the mesh generation and unity integration, so same as MapzenGO.

-What will happen to MapzenGo?
It really isn’t an easy job building worlds from scratch, there’s millions of thing to do. I can’t do it all for two project at the same time so I’ll switch MapzenGo to maintanence mode. I’ll keep fixing bugs and answering everything as much as I can but I won’t add new features and stuff anymore. It’ll be like an “Introduction to GeoJson mesh generation in Unity3D”. Again Mapbox will be open source anyway so you won’t miss out on anything!

-And blog posts?
I probably won’t have much time for detailed technical posts, at least until the release. I’ll post images, videos or anything though. I’ll keep this blog alive and try to write technical stuff as much as I can. Meanwhile you can follow me on Twitter for updates and mail me for anything. You may already know that I love talking, so don’t hesitate to say hi!

Thanks for everything guy, it has been awesome working on MapzenGo and doing this blog. Please try out the Mapbox SDK Unity beta and tell us what you think. It’s a developer tool afterall, your feedback is extremely important for us.

Cheers,
Baran