Android Unity Game Development Blog: Drawing Polygons!

Covyne Entertainment
3 min readJan 30, 2021

--

Problem:

I want to draw a hexagon shape on top of an existing hexagon mesh and have that shape flash.

Simple huh?

lol

Solution:

So here I talked about how to drawing outlines around our hexagons. We’re going to take a similar approach. But this time, we’re going to draw the triangles as a mesh, instead of just the outlines (so all the green triangles below):

Here’s the code that takes a single hexagon GameObject, finds the vertices with the highest y value, copies them, and creates a new polygon with those values:

private void CreatePoly(GameObject hexTile, GameObject renderer)
{
//Grab mesh filter's shared vertices of the hexagon
MeshFilter hexMesh = hexTile.GetComponent<MeshFilter>();
Vector3[] vertices = hexMesh.sharedMesh.vertices;
//Order the hexagon's vertices by y coord.
//Take the first 10
//Get the distinct vertices
//Set the height
//Convert to array
Vector3[] distinctVertices = vertices.OrderBy(v => v.y)
.Take(minVertices)
.Distinct()
.Select(v => new Vector3(v.x, Height, v.z))
.ToArray();
//Instantiate our new selection object
//(it just has a MeshRenderer attached to it
GameObject selection = Instantiate(renderer, transform);
//Add a new mesh filter to our selection object
MeshFilter filter = selection.AddComponent<MeshFilter>();
//Create a new mesh with our vertices hexagon triangles
Mesh mesh = new Mesh
{
vertices = distinctVertices,
triangles = HexagonTriIndices
};
//Recaclulate norms
mesh.RecalculateNormals();
//Set our new mesh
filter.mesh = mesh;
//Position the new selection object
selection.transform.position = hexTile.transform.position;
}

And here’s the whole class file (sorry about formatting, Medium doesn’t handle it well):

using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class HexagonSelection : MonoBehaviour
{
//The height of the polygon
public float Height;
//The player
public PlayerAvatar PlayerAvatar;
//The selection prefab (colour of the selection)
public GameObject TileSelectionPrefab;
//the hexagon's parent tag
public string HexagonsTag;
//Store the selected tilee (avoid duplicates)
private readonly List<GameObject> selectedTiles = new List<GameObject>();
//Min vertices to create a hexagon
private static readonly int minVertices = 10;
//The search directions
private static readonly Vector3[] tileDirections
= new Vector3[] { Vector3.left,
Vector3.right,
Vector3.forward,
Vector3.back,
Vector3.right + Vector3.forward,
Vector3.back + Vector3.left,
Vector3.back - Vector3.left,
Vector3.right - Vector3.forward,
};
//The triangle indices for our hexagon shape
private static readonly int[] HexagonTriIndices = new int[12]
{
0,1,2,
2,5,0,
5,2,3,
3,4,5
};
private void Awake()
{
//When the player clicks the player avatar, highlight the selected tile
PlayerAvatar.OnPlayerSelected += (player) =>
HighlightOccupiedTile(player.GetComponent<Renderer>().bounds.center);
}
private void HighlightOccupiedTile(Vector3 position)
{
Ray ray = new Ray(position, Vector3.down);
if (Physics.Raycast(ray, out RaycastHit hit))
{
Transform hitTransform = hit.transform;
GameObject hexTile = hitTransform.gameObject;
CreatePoly(hexTile, TileSelectionPrefab);
CreatingSurroundingPolys(hexTile, TileSelectionPrefab);
}
}
private void CreatePoly(GameObject hexTile, GameObject renderer)
{
//Grab mesh filter's shared vertices of the underlying hexagon
MeshFilter hexMesh = hexTile.GetComponent<MeshFilter>();
Vector3[] vertices = hexMesh.sharedMesh.vertices;
//Order the hexagon's vertices by y coord.
//Take the first 10
//Get the distinct vertices
//Set the height
//Convert to array
Vector3[] distinctVertices = vertices.OrderBy(v => v.y)
.Take(minVertices)
.Distinct()
.Select(v => new Vector3(v.x, Height, v.z))
.ToArray();
//Instantiate our new selection object
GameObject selection = Instantiate(renderer, transform);
//Add a new mesh filter to our selection object
MeshFilter meshFilter = selection.AddComponent<MeshFilter>();
//Create a new mesh with our vertices and standard hexagon triangles
Mesh mesh = new Mesh
{
vertices = distinctVertices,
triangles = HexagonTriIndices
};
//Recaclulate norms
mesh.RecalculateNormals();
//Set our new mesh
meshFilter.mesh = mesh;
//Position the new selection object
selection.transform.position = hexTile.transform.position;
}private void CreatingSurroundingPolys(GameObject hexTile, GameObject prefab)
{
//Get the center of the tile
Vector3 center = hexTile.GetComponent<Renderer>().bounds.center;
//For each direction
foreach (Vector3 direction in tileDirections)
{
//Create a ray in the direction
Ray ray = new Ray(center, direction);
//Find a tile in the current direction
GameObject selectedTile = HighlightSurroundingTile(ray, prefab);
if (selectedTile != null)
{
//If we found one, add it to our selected tiles
selectedTiles.Add(selectedTile);
}
}
}private GameObject HighlightSurroundingTile(Ray ray, GameObject prefab)
{
//Cast the ray
if (Physics.Raycast(ray, out RaycastHit hit, Mathf.Infinity))
{
//we got a hit
Transform hitTransform = hit.transform;
//Make sure it's a hexagon
if (hitTransform.parent.CompareTag(HexagonsTag))
{
GameObject hexTile = hitTransform.gameObject;
if (!selectedTiles.Contains(hexTile))
{
CreatePoly(hexTile, prefab);
}
return hexTile;
}
else
{
return null;
}
}
return null;
}
}

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

--

--

No responses yet

Write a response