The Trouble With Tiles
All of Epistory’s levels start as an isometric RPG in Tiled (as explained in this prior article). This is a great foundation to build on - but it brings some technical limitations which we have to deal with. For example, we have to respect the TiledToUnity plugin rule that each tile must be a square of equal size. It doesn’t help that any tile rotation must be done as a duplicate tile instead of a random effect.
As a result of this, the tiles use to build each level stand out too clearly. We can see the seams, the joins, the patterns. The effect is fatal to immersion within the game world.
This old screenshot illustrates the problem nicely. Each tile is the same as the previous one, creating a very obvious pattern. This is just a small example - sometimes the whole screen will have the same tile, interrupted only by the occasional prop or decoration.
In this article, I will guide you through the steps we used to break this ugly pattern and improve the overall look of the ground tiles, which currently look like the screenshot below. It’s unlikely that we will change the tile’s look again - but you never know.
Start at the Start
If it sounds obvious, it’s probably because it is! Rotating each tile will help make it look different and vary the seams created where they join.
We started by rotating our tiles randomly with an editor script. Since our goal in art direction was to create a hand-made paper world, we decided early on that a tile would be considered an independent square of paper. Based on this fact, we agreed that imperfect tiling between two tiles was acceptable: meaning that rotation gives us variation. The result was better but still a bit jarring.
Lean Towards the Abnormal
Because each tile is supposed to be a piece of paper, it’s hard (not to mention expensive) to make each one visually unique. We aimed to solve this by dynamically changing the normal map on each individual tile.
A normal map is a 2D image used to replace or modify the normals of a 3D surface. Because our tile models are mostly flat, we use normal maps and lighting to give them some paper-looking wrinkles.
Here’s how we modified our ground shader in Shader Forge:
- world position.
- a parameter which allow us to tweak how much a change in world position affects the overall look.
- frac. It takes only the fractional part of the input. Effectively producing a value from 0 to 1, based on the world position.
- append allows us to create a vector 2 (UV in our case).
- normal map sampling.
- normal blending. You cannot blend normals the same way you blend colors so we use a custom formula.
The effect of this is that instead of having one normal map per tile and limited to its bounds, we have two normals, whose UVs will depend on their world position. This effectively spans (and repeats across) the whole level. If you look carefully you can see that one of them will have U & V depending on the positions X & Z while the other will map U & V to Z & X. This “crisscross” allows us to have very different looking tiles each time, instead of having the pattern being simply repeated less often.
If you want a more visual way of understanding this, you can see it in the editor view. We created a gif but it was too heavy to be posted inline. You can find it here.
You can see that when I move the tiles, the normal on top of it doesn’t move. The apparent seam on the normal is a result of the tile rotation around Y.
As a bonus, we also added a detail texture. It’s a common technique so I won’t explain it here - but here’s the shader forge screenshot:
This was the first time I did major shader work and it turned out quite well in my opinion. With the current art direction we had to improvise a bit - but we successfully fixed the tiling problem with no rework on the assets. This results in a seamless, believable game world.