I have a hex based, fully flat tilemap the tiles' mesh currently isn't generated, but a static mesh file containing 6 vertices, UV mapping, etc.

enter image description here

Then I saw this picture on Unity Answers:

enter image description here

I'd like achieve this. Which is:

  • To morph my hexes' vertices randomly in every direction
  • while they are all seamlessly still connected.

(But without having a height for now for simplicity's sake. But that could be a future step.)

So if I move a vertex0 of Hex A, the corresponding, opposing index, vertex3 of the neighbouring Hex B will move accordingly, like they are all part of one big mesh.

Water tiles would be an exception

  • They would be flat: their vertices' Y (up axis) would be constant zero,

  • thus I would set every shore tile's water neighbouring borders' vertices' Y to 0 as well. (now that's an ugly sentence)

As you can see I have some vague, high level idea about how I would try to achieve parts of this, but code-wise I'm pretty lost. Could you help me? Thanks in advance!

  • \$\begingroup\$ Are you already familiar with the Mesh class and how it can be used to create and change geometry at runtime? Another option would be to use a vertex shader which displaces the vertices before rendering based on sampling a noise pattern in world-space. \$\endgroup\$
    – Philipp
    Aug 15, 2022 at 13:34
  • \$\begingroup\$ I saw some code snippets but nothing more. The shader option could be easy with shader graph I guess. But I'm not familiar with that either. \$\endgroup\$
    – Tudvari
    Aug 15, 2022 at 14:00

1 Answer 1


Myself, I would implement this in the shader.

Use a vertex colour to mark which vertices should be displaced vs. not (so for example, paint all interior land vertices red, and all shore or water vertices black).

Inside the vertex shader, compute the worldspace position of the vertex. Run that position through a noise function like Simplex or Perlin Noise to generate a pseudo-random 2D offset vector. Multiply that vector by the displacement mask stored in the vertex colour (so it gets zero'd out for water vertices), then add it to the vertex position before projecting it to the screen.

This gives you uneven, random-looking warping of the land hexes, without needing tons of unique mesh variants (just one for each combination of water adjacencies). Since the offset vector depends on worldspace position, wherever two vertices coincide at the same position (like two tiles meeting at a shared corner), both vertices will get the same offset, so they'll move as though glued together, even if they're rendered as two completely different meshes with no knowledge of one another. And you'll get the same result frame to frame, so it won't move or animate (unless you want it to).

You can get away with even cheaper, discontinuous noise functions, if your vertices are always perfectly positioned to match up, or you do a quick bit of rounding before applying the noise. The continuous noise functions just give you a bit more leeway for small alignment errors to produce only small offset differences (hopefully sub-pixel-sized), and if you're using a shader graph, they're directly available as nodes to use for quick prototyping.

  • \$\begingroup\$ And I would use 3 different noise textures to sample the x, y, z offsets? If yes, then maybe I have a chance. Except the vertex painting. I have no clue about that :D \$\endgroup\$
    – Tudvari
    Aug 15, 2022 at 16:14
  • 1
    \$\begingroup\$ It doesn't need to be a texture at all, but if you do use a texture you can pack x, y, z into a single texture's RGB channels, or sample the same greyscale texture at 3 different positions, either one works. Vertex colours are reasonably straightforward to add — you can find guides for Unity or any 3D content creation tool you like with a quick search. \$\endgroup\$
    – DMGregory
    Aug 15, 2022 at 17:22
  • \$\begingroup\$ The seamless morphing was easy to achieve, thanks! Regarding the vertex painting I'm still searching. Maybe I'll just reuse existing code to set variables in the shader for each hex from a script because it's just one extra line. But it will create new material instances which is bad for performance... I can't find per-instance properties in ShaderGraph to optimize this a bit like in built-in shaders. \$\endgroup\$
    – Tudvari
    Aug 16, 2022 at 11:09
  • \$\begingroup\$ Also another problem for me is that I want to highlight the tiles which I implemented easily because the vertices were fixed. But now they are modified on the GPU. Is there a way to access the new vertex positions? I guess if not my two options are to write a highlight shader... or to ditch the shader solution for the hex morphing all-together. But I once tried implementing a highlight and after hours of trying I gave up. :\ \$\endgroup\$
    – Tudvari
    Aug 16, 2022 at 11:12
  • \$\begingroup\$ You can open up your hex mesh using the Mesh class, make copies of it, and set the vertex colours of those copies in script. For matching the highlights, just use the same noise formula in your highlight drawing shader and the two will line up perfectly. \$\endgroup\$
    – DMGregory
    Aug 16, 2022 at 11:21

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .