OK so it has been ages since I last posted something useful here, I’m a bit rusty and my aged post editor is torturing me, but I’ll do my best.
Let’s talk a little bit more about Unity and Hexagons.
Why? Well pretty much because both are the coolest things in their fields.
Unity is just stupefyingly easy and fun. Likewise for hexagons, they are incredibly sexy as well. So yeah, Unity & Hexagons.
I’ll assume that you’ll know the basics here, like creating a script etc. Oh and that being said, I’m a rather newbie in Unity as well so my way of doing things may be wrong or (most likely) not optimal. I work in XNA-ish way a lot and pretty much refuse to learn Unity practices etc. I may be so totally wrong on doing that but yea, that’s how it is for now.
Anyway, let’s get started;
In this post, we’ll create a simple hexagon for future usage. We’ll create it vertex by vertex, not using a 3D model or anything. Most important point here is to make it flexible and manageable for future projects. This is pretty much what we’re trying to achieve in the end ( first pic );
First of all let’s create a Hierarchy like in that second pic above.
Nothing fancy there really as we’ll create everything in code. Told you I don’t like drag&drop stuff and I’ll do it all xna style.
World and HexHolder are empty game object, that’s pretty much it.
Now as another easy step, let’s create a simple script for “Hex”;
Once again, nothing fancy.
Two things to note here;
(1) is that I added a public Vector2 HexPosition to the Hex script. This is not the x,y,z coordinates of our hexagon. This is the location of any particular hex on the base hex grid ( see that final pic above, whole surface is a big huge grid that doesn’t exists in code but does theoretically ).
The grid we’ll be using is something like this; ( indexing may be different though, I just googled this picture )
(2), we have another object, HexModel inside this one. What’s that? That’s all the vertices, edges and whatever of our Hex. Pretty much the physical or visual stuff wrapped all together. All that stuff gets extremely hairy so I just created a sub class for them.
Speaking of the model, let’s look at how we create that one;
This InitializeModel function actually is inside Hex class. Why? Well mainly because I wasn’t able to find a useful constructor implementation for components. So instead, after setting some important values, I call model creator myself. We’ll look into that later on.
So first, we created a new game object and added that new component HexModel to that. We keep the component reference in Hex, not the game object ( not a big difference but saves us some calls ). Then we set hex parent to be current object’s transform.
This will make HexModel a subobject to Hex in the game hierarchy.
Setting position to zero as it’s relative to the Hex and we want them both at the same place ( for now ) for obvious reasons.
Shader is just a standard share, I’ll add that to files but won’t talk about it here.
And texture is just a filler texture, nothing special.
So where are we standing now?
We have a world hierarchy, a hex wrapper “Hex” and a model “HexModel”.
Well we actually haven’t created the HexModel yet so let’s do that now.
Add a new script inside the assets as normal and open it with whatever IDE you’re using BUT this time we’ll make a vital change/addition to the script file;
Notice the new line right above the class definition. That lines says, this component requires a MeshFilter and MeshRenderer in whatever object it’s attached to. In other words, this script can only be attached to physical objects ( with mesh stuff ).
First property is just optional, I always like to keep a reference to parent object if possible.
Then, since this will be a mesh object, there are some stuff we have to have for visualization, like Vertices, normals etc.
The idea is to set all these vertices, normals, UV and let Unity draw them on screen.
void Start ()
{
Parent = transform.parent.GetComponent<Hex>();
Vertices =newVector3[24];
UV =newVector2[24];
DrawTopAndBottom();
DrawSides();
SetTriangles();
var mesh =newMesh { name =“Hex Mesh” };
GetComponent<MeshFilter>().mesh = mesh;
mesh.vertices = Vertices;
mesh.uv = UV;
mesh.triangles = Triangles;
mesh.normals = Normals;
}
I don’t even know why I’ve been posting pics, not embedded code really. Anyway here it is, should be easier now.
This is the start function of HexModel. First we get and save a reference for the parent objects Hex script, then we create arrays for vertices and UV.
Next 3 functions creates vertices, they are extremely straight forward and simple, not sure if there is anything to talk about them. I might do another post in the future but I’ll skip them for now. They’ll of course be in the sample solution below.
And 3rd part is, now that we set vertices and UV’s, we tell Unity to use them as this current game objects mesh.
Now two important things,
First we’ll create a few global variable for our hexagon grid, like hex radius and related values.
Simply create a new C# script file and paste all this into that;
using System;
public static class Globals
{
public static int Radius =8;
public static int Height =2* Radius;
public static float RowHeight =1.5f* Radius;
public static float HalfWidth = (float)Math.Sqrt((Radius * Radius) – ((Radius /2) * (Radius /2)));
public static float Width =2* HalfWidth;
public static float ExtraHeight = Height – RowHeight;
public static float Edge = RowHeight – ExtraHeight;
}
Those are some generic values all calculated using base radius value. I don’t like static stuff for obvious reasons but I feel like this is OK and since it makes everything much easier… yeah.
And now we’ll create the script that’ll run first and create everything. Remember that “World” object we created in game hierarchy? Yeah we’ll use that as script host for this, so create a “World” script and attach it to the World object.
publicclassWorld : MonoBehaviour {
Dictionary<Vector2, Hex> Hexes { get; set; }
void Start ()
{
Hexes =newDictionary<Vector2, Hex>();
var position =newVector2(0,0);
var pos = ToPixel(position);
var hex =newGameObject();
hex.AddComponent(“Hex”);
var hm = hex.GetComponent<Hex>();
hm.HexPosition = position;
hex.transform.position = pos;
hex.transform.parent = transform.FindChild(“HexHolder”);
hm.InitializeModel();
this.Hexes.Add(position, hm);
}
In our “World” we just have one single dictionary for now, which will help us to keep track of all hexagons we have in this world.
Then we’re creating a new hexagon at grid position 0,0. Remember this is grid position, not global x,y,z of the hexagon.
We send that grid position to a function to convert it to exact pixel coordinates, that’s the function I posted long ago in another post. Won’t go into that here as it is long and boring but it’s there in the code if you want to check it out.
It’s standard stuff really, we create a new game object, attach our Hex script to it. Set it’s HexPosition, set it’s pixel position, added it under the “HexHolder” object we created at the begining ( parent-child relation here, just to keep stuff organized ). Then we call InitializeModel function which will create the flesh and bones of our hex and add it to the list for future references.
Well we’re pretty much done, just one little thing, do no forget to add “Resources/Textures/” folder into assets and create a “Hex” texture there. Our HexModel will look for it and if it’s not able to find it, it’ll look all dark grayish.
At this point, if you run it on Unity and play with the camera angles a little bit, you should get something that looks like this;
Well it’s not the worlds most beautiful hexagon but it’s 100% your!
You can add lighting and whatever to make it look better really,
Better?
Yeah I guess a little bit better.
You can find the whole sample here;
Hexagons.zip (176.86 kb)
For some reason it won’t load the scene by itself though, remember to load the scene yourself after opening the project ( file -> open scene -> hexagons ).
Anyway, let me know if you have any question, liked the post or wanted to say hi.
I had to close the comments due to increasing spams but you sure can always mail me for anything; brnkahyaoglu@gmail.com
See you later everyone!
public static float HalfWidth = (float)Math.Sqrt((Radius * Radius) … that is 1 right? .. ever
Errm not really, no. Why would it be?
Math.Sqrt((8*8) – (4*4)) , that’s like 6.9