This tutorial is the second part of a series about hexagon maps. The previous installment laid the foundation of our grid and gave us the ability to edit cells. Each cell has its own solid color. The color change between cells is abrupt. This time we'll introduce transition zones, blending between colors of adjacent cells.

Cell Neighbors

Before we can blend between cells colors, we need to know which cells are adjacent to each other. Each cells has six neighbors, which we can identify with a compass direction. The directions are northeast, east, southeast, southwest, west, and northwest. Let's create an enumeration for that and put it in its own script file.

public enum HexDirection { NE, E, SE, SW, W, NW }

What's an enum ? You use enum to define an enumeration type, which is an ordered list of names. A variable of this type can have one of these names as its value. Each of these names corresponds to a number, by default starting at zero. They are useful whenever you need a limited list of named options. Under the hood, enums are simply integers. You can add, subtract, and cast them to integer and back. You could also declare them to be of a handful of other types, but integers are the norm.

Six neighbors, six directions.

To store these neighbors, add an array to HexCell . While we could make it public, instead we'll make it private and provide access methods using a direction. Also ensure that it serializes so the connections survive recompiles.

[SerializeField] HexCell[] neighbors;

Do we need to store the neighbor connections? We could also determine the neighbors via coordinates, and then retrieve the desired cell from the grid. However, storing the relations per cell is straightforward, so we'll do that.

The neighbor array now shows up in the inspector. As each cell has six neighbors, set the array size to 6 for our Hex Cell prefab.

Our prefab comes with room for six neighbors.

Now add a public method to retrieve a cell's neighbor in one direction. As a direction is always between 0 and 5, we don't need to check whether the index lies within the bounds of the array.

public HexCell GetNeighbor (HexDirection direction) { return neighbors[(int)direction]; }

Add a method to set a neighbor too.

public void SetNeighbor (HexDirection direction, HexCell cell) { neighbors[(int)direction] = cell; }

Neighbor relationships are bidirectional. So when setting a neighbor in one direction, it makes sense to immediately set the neighbor in the opposite direction as well.

public void SetNeighbor (HexDirection direction, HexCell cell) { neighbors[(int)direction] = cell; cell.neighbors[(int)direction.Opposite()] = this; }

Neighbors in opposite directions.

Of course this assumes that we could ask a direction for its opposite. We can support this, by creating an extension method for HexDirection . To get the opposite direction, add 3 to the original direction. This only works for the first three directions though, for the others we have to subtract 3 instead.

public enum HexDirection { NE, E, SE, SW, W, NW } public static class HexDirectionExtensions { public static HexDirection Opposite (this HexDirection direction) { return (int)direction < 3 ? (direction + 3) : (direction - 3); } }

What's an extension method? An extension method is a static method inside a static class that behaves like an instance method of some type. That type could be anything, a class, an interface, a struct, a primitive value, or an enum. The first argument of an extension method needs to have the this keyword. It defines the type and instance value that the method will operate on. Does this allow us to add methods to everything? Yes, just like you could write any static method that has any type as its argument. Is this a good idea? When used in moderation, it can be. It is a tool that has its uses, but wielding it with abandon will produce an unstructured mess.