[info]This tutorial explains how to construct a grid in code. If you want to setup grids in the editor instead, see Working with grids in the editor.[/info]
This tutorial shows you how to set up a hexagonal grid for a 2D game. I assume you already have a tile object defined that you want to use in your grid, and that is of type SpriteCell. Grids come with a few built-in cell prefabs, but those are intended for our examples. In general, you would make your own cells for your specific game.
[dropcap style=”dark”]1[/dropcap]Start with the main class which will build the grid, and handle inputs to the grid. Here is the shell for that class, plus the declarations we will need:
using UnityEngine; using Gamelogic; //Include this to use GLMonoBehaviour using Gamelogic.Grids; //Include this to use Grids public class PointyHexTestDoc : GLMonoBehaviour //(GLMonoBehaviour has some extra convenience functions, such as a generic Instantiate) { public SpriteCell cellPrefab; //The is the prefab that will be used for cells. public GameObject root; //This is the root object for all cells //A grid of pointy hex cells that take SpriteCells as objects private PointyHexGridgrid; //A map that can convert PointyHexPoints to Vector3 private IMap3D map; public void Start() { BuildGrid(); } private void BuildGrid() { // ... } public void Update() { // ... } }
[dropcap style=”dark”]2[/dropcap]In the BuildGrid method, define the grid structure. This is the data structure that will contain the cells, and it works very similar to a 2D array. The simplest way to do this is to use one of the standard shape functions provided for each grid type. These functions determine the shape of the grid (not the shape of the cells!) For this tutorial, we will use a rectangular shape. (Fat rectangles have one cell extra in every second row. Thin rectangles have one cell less in every second row. Ragged rectangles have the same number of cells in each row.)
const int width = 3; const int height = 5; grid = PointyHexGrid.FatRectangle(width, height);
(There are two more advanced ways to create different shapes if the standard shapes do not meet your needs. See Constructing Grids for more information).
[dropcap style=”dark”]3[/dropcap]Next, we need to define a map. A map determines where the grid is located in space. Maps also makes it possible to align grids in a rectangle. The following will make a map that aligns our grid to the center of a rectangle, which we conveniently choose to coincide with the edges of the screen:
map = new PointyHexMap(cellPrefab.Dimensions) .WithWindow(ExampleUtils.ScreenRect) .AlignMiddleCenter(grid) .To3DXY(); //Converts 2D map to a 3D map. }
There are more commands that you can chain in map creation expressions that give you more low-level control over the positioning and rotation of a grid. For more information on how maps work, see Working with Maps.
[dropcap style=”dark”]4[/dropcap]The next step is to instantiate our cells, and put them in the right positions using our map. We also assign them to corresponding positions in the grid data structure:
foreach (PointyHexPoint point in grid) { SpriteCell cell = Instantiate(cellPrefab); Vector3 worldPoint = map[point]; cell.transform.parent = root.transform; cell.transform.localScale = Vector3.one; cell.transform.localPosition = worldPoint; //Depending on your game, you will have a different //cell that will have different methods. cell.Color = ExampleUtils.Colors[point.GetColor3_7()]; cell.name = point.ToString(); //This is used by gizmos in the editor grid[point] = cell; }
Note that we use points to access the elements of a grid. Each grid uses its own point type. A grid point works similar to a 2D Vector, except that coordinates are always integers. Most point types provide static constants that correspond to the cardinal directions of the grid. For instance, RectPoint provides North, East, South, West. PointyHexPoint provides NorthEast, NorthWest, West, SouthWest, SouthEast, and East.
[dropcap style=”dark”]5[/dropcap]To make our cells clickable, we need to process mouse inputs, typically in the Update function
public void Update() { if (Input.GetMouseButtonDown(0)) { Vector3 worldPosition = GridBuilderUtils.ScreenToWorld(root, Input.mousePosition); PointyHexPoint hexPoint = map[worldPosition]; if (grid.Contains(hexPoint)) { //Just toggle the cell highlight //Of course, your own cell may not have this method grid[hexPoint].HighlightOn = !grid[hexPoint].HighlightOn; } } }
That is the basics of setting up a grid. Here is the entire file.
using UnityEngine; using Gamelogic; using Gamelogic.Grids; //Include this to use Grids public class PointyHexTest : GLMonoBehaviour //(GLMonoBehaviour has some extra convenience functions, such as a generic Instantiate) { public SpriteCell cellPrefab; //The is the prefab that will be used for cells. public GameObject root; //This is the root object for all cells private PointyHexGridgrid; private IMap3D map; public void Start() { BuildGrid(); } private void BuildGrid() { const int width = 3; const int height = 5; grid = PointyHexGrid .FatRectangle(width, height); map = new PointyHexMap(cellPrefab.Dimensions) .WithWindow(ExampleUtils.ScreenRect) .AlignMiddleCenter(grid) .To3DXY(); //Converts 2D map to a 3D map. foreach (PointyHexPoint point in grid) { SpriteCell cell = Instantiate(cellPrefab); Vector3 worldPoint = map[point]; cell.transform.parent = root.transform; cell.transform.localScale = Vector3.one; cell.transform.localPosition = worldPoint; //Depending on your game, you will have a different //cell that will have different methods. cell.Color = ExampleUtils.Colors[point.GetColor3_7()]; cell.name = point.ToString(); //This is used by gizmos in the editor grid[point] = cell; } } public void Update() { if (Input.GetMouseButtonDown(0)) { Vector3 worldPosition = GridBuilderUtils.ScreenToWorld(root, Input.mousePosition); PointyHexPoint hexPoint = map[worldPosition]; if (grid.Contains(hexPoint)) { //Just toggle the cell highlight //Of course, your own cell may not have this method grid[hexPoint].HighlightOn = !grid[hexPoint].HighlightOn; } } } }