[Solved] Hex Grid on Terrain

I would like to preface this thread with saying that we are looking for advice on how to solve our problem the “right” way in Unity instead of having a piece of code that needs fixing.

We have a 3d project with a terrain object on which we want to project a hexagonal grid (which can be directly on the ground or hovering slightly above, which allows the edges of the hexes to remain straight over curved terrain as long as the offset is high enough), similar to XCOM’s tactical grid. We also need to be able to highlight any given subset of cells by marking their outlines (ideally also disconnected subsets)
The mathematics behind the grid arent an issue, we have working methods to translate from grid space into kartesian space and the other way around. Our issue lies in rendering the grid, or more precisely in rendering it the right way. As we are new in working with Unity we arent familiar with what the proper efficient way is to do so.
Currently we are creating a mesh from scratch each tick and are changing vertex colors for each highlighted hex. This creates a working grid but seems quite ineffcient however.

That is why we are wondering what the right way to start would be, what structure to use and how to render and highlight the grid correctly and efficiently, ideally with the individual hexes not being their own gameObject each, since that also seems like a lot of project clutter.

Thanks for any help in advance!

I’m not sure what that means… but I’ll let it be for now. Keep in mind that you have posted in the scripting area of the forum which is all about “code that needs fixing.”

We humans are abysmal at judging what is efficient in a computer. If you have 5 hexes it’s probably fine… 50 hexes? Maybe… 500000 hexes? Probably not.

Have you even done any profiling or is this just speculative optimization?

DO NOT OPTIMIZE “JUST BECAUSE…” If you don’t have a problem, DO NOT OPTIMIZE!

If you DO have a problem, there is only ONE way to find out. Always start by using the profiler:

Window → Analysis → Profiler

Failure to use the profiler first means you’re just guessing, making a mess of your code for no good reason.

Not only that but performance on platform A will likely be completely different than platform B. Test on the platform(s) that you care about, and test to the extent that it is worth your effort, and no more.

https://discussions.unity.com/t/841163/2

Remember that optimized code is ALWAYS harder to work with and more brittle, making subsequent feature development difficult or impossible, or incurring massive technical debt on future development.

Notes on optimizing UnityEngine.UI setups:

https://discussions.unity.com/t/846847/2

At a minimum you want to clearly understand what performance issues you are having:

  • running too slowly?
  • loading too slowly?
  • using too much runtime memory?
  • final bundle too large?
  • too much network traffic?
  • something else?

If you are unable to engage the profiler, then your next solution is gross guessing changes, such as “reimport all textures as 32x32 tiny textures” or “replace some complex 3D objects with cubes/capsules” to try and figure out what is bogging you down.

Each experiment you do may give you intel about what is causing the performance issue that you identified. More importantly let you eliminate candidates for optimization. For instance if you swap out your biggest textures with 32x32 stamps and you STILL have a problem, you may be able to eliminate textures as an issue and move onto something else.

This sort of speculative optimization assumes you’re properly using source control so it takes one click to revert to the way your project was before if there is no improvement, while carefully making notes about what you have tried and more importantly what results it has had.

FINALLY…

How to report your problem productively in the Unity3D forums:

http://plbm.com/?p=220

This is the bare minimum of information to report:

  • what you want
  • what you tried
  • what you expected to happen
  • what actually happened, log output, variable values, and especially any errors you see
  • links to documentation you used to cross-check your work (CRITICAL!!!)

The purpose of YOU providing links is to make our job easier, while simultaneously showing us that you actually put effort into the process. If you haven’t put effort into finding the documentation, why should we bother putting effort into replying?


Do not TALK about code without posting it. Do NOT retype code. Copy/paste and post code properly. ONLY post the relevant code, and then refer to it in your discussion. Do NOT post photographs of code.

If you post a code snippet, ALWAYS USE CODE TAGS:

How to use code tags: https://discussions.unity.com/t/481379

I‘d probably generate a hex-grid mesh for the given map size upon starting the map, or if they are all the same size or there are only a handful of size variations you can generate them offline or make them in blender.

Then for highlighting take a simple single-cell hex-grid mesh that matches the size of your hex cells and draw it wherever you need, perhaps with a minimally higher y value to ward off z fighting. You could also use the line renderer or a particle system emitter that emits particles along the outline of the hex cell (I believe that‘s possible in both ParticleSystem and vfx graph).

Point being: render the always visible grid as a single mesh and selected cells by drawing additional hex visuals on top.

If the hex cells need to show height variations, making the single mesh approach unusable, I don‘t think it matters much if you draw a couple dozen or hundreds of hex cell meshes.You may want to look into GPU instancing but first profile to see if that is really necessary.

I too am doing a Hex style at the moment, however mine is more tile based:


So that technically doesn’t help, as those outlines are world space canvases.

However the tutorial that helped me, especially with a proper setup for grid, was:

And I think in his video before that one, he sets up his grid outlines as lines, and the code only goes off of X,Z. However I think you mention that it won’t be straight lines from point to point, so not sure if his examples work in your particular case. But I’d figured I’d mention it. :slight_smile:

However wracking my brain on this, I’m recalling “Unity Splines” for some reason, and would assume to get the X,Z of corner to corner, then read terrain data between those points, and every vert that is “in line” give proper up/down positions on where the line is to curve.

Take that with a grain of salt though, I’m just thinking out loud.

As long as we’re dropping bits of simple positional logic for hexes, I might as well drop my collection of linkies:

Hexagonal maps (hexmaps): (One of these is the same guy posted by WideEyed above!)

2 Likes

Nice call out! In catlike’s example he uses the terrain shader to project the grid outline:
https://catlikecoding.com/unity/tutorials/hex-map/part-15/

Thanks! We’ll definitely look into the particle system approach, however the highlighting method using different meshes seems more applicable for our problem.

When talking about rendering each cell individually (if necessary), can i render multiple meshes with one MeshRenderer or would i have to create a seperate one for each mesh?

It is frequently on sale. Buy it (I am NOT affiliated with the publisher on any way) and learn how it works and improve upon it. You can just keep a database about the grid, positioning, coordinates and the project the grid on the terrain as needed and where it is needed.

1 Like