Android Unity Game Development Blog: Drawing a Simple Outline around a Hexagon
Problem:
I have a map of 3d hexagon shapes and I’d like to draw a polygon in around the top most the face of each of the hexagons.
So from this:

To this:

Solution:
The solution will consist of:
- In the Start() method we will loop through our hexagons and collect all the vertices that are on the top each hexagon mesh. There will be a total of 10 vertices for a hexagon shape. Why 10? Remember, a polygon mesh share vertices where where the triangles of the mesh meet.

2. We will then make a CreateHexagon() method taking all the hexagon vertices. Using OrderBy we will order them by y-coord (height). Of the ordered vertices we will Take the first 10 vertices. Of the 10 heighest vertices, we will select the Distinct ones - there should be 6. Of those 6 vertices we will Select each and create a new Vector3 with our desired height. We will then Select each of our newly created vertices and use TransformPoint to transform them to world coordinates. Finally we will store them in our hexList field as an Array so we can draw them easily later.
3. Next we will use the OnRenderObject() method to loop through each of our new hexagons and call a DrawLine method (remembering to draw the last line between vertex index 5 back to 0.
4. Finally we will call the DrawLine method. To be honest, I only barely understand what this method does as I lifted it from a forum post here. I believe it simpy uses a Scene View rendering package to draw on the screen, making sure it can draw with the current Camera, and that if does not “draw over” objects that are in front of it.
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
using UnityEngine.Rendering;public class HexagonOutlines : MonoBehaviour
{ public Color Color; public float Width; public float Height; private readonly List<Vector3[]> hexList = new List<Vector3[]>(); private static readonly int minVertices = 10; void Start()
{
foreach (Transform child in transform)
{
CreateHexagon(child);
}
} private void CreateHexagon(Transform child)
{
Transform tChild = child.transform; Vector3[] vertices = child.GetComponent<MeshFilter>()
.sharedMesh.vertices; if (vertices.Length > minVertices)
{
hexList.Add(vertices
.OrderBy(vertex => vertex.y) //get top-most vertices
.Take(minVertices) //take the top 10
.Distinct() // get the distinct ones
.Select(v => new Vector3(v.x, OutlineHeight, v.z))
.Select(v => tChild.TransformPoint(v)) // to world coords
.ToArray()); // store them as Array for later
}
else
{
Debug.LogWarning($"bad hexagon {tChild.position}");
}
} void OnRenderObject()
{
foreach (Vector3[] vert in hexList)
{
for (int i = 0; i < vert.Length - 1; i++)
{
DrawLine(vert[i], vert[i + 1], Width);
}
DrawLine(vert[vert.Length - 1], vert[0], Width);
}
} public void DrawLine(Vector3 start, Vector3 end, float thickness)
{
Camera c = Camera.current;
if (c == null) return; // Only draw on normal cameras
if (c.clearFlags == CameraClearFlags.Depth
|| c.clearFlags == CameraClearFlags.Nothing)
{
return;
} // Only draw the line when it is the closest to the camera
// (Remove the Z-test code)
CompareFunction prevZTest = Handles.zTest;
Handles.zTest = CompareFunction.LessEqual;
Handles.color = Color;
Handles.DrawAAPolyLine(width, new Vector3[] { start, end });
Handles.zTest = prevZTest;
}
}