FX Hex Grid will generate a Hex based map using a base Hex geometry and an input for Map Height Width. Each Hex section will have a script component that contains its location in the map. Top left is 1,1.
This is very basic and is intended as a starting point for Hex based map generation. Modify it to fit your game. Enjoy.
Current Build Version 1.5.0 c#
New features:
Hex meshes are now procedurally generated.
2.Hex orientation can be changed to have either the pointy part of the hex on top or the flat part of the hex on top.
Changes:
Completely rewritten in C#
Modular scripting. Gives easy access to hex generator or map generator with out player controls getting in the way.
Removed:
Map Wrapping it didn’t really work I may revisit it again later.
Keep symmetrical. Will probably bring this back.
Setup v1.5.0
Create an empty gameObject and apply the scripts FX_Map_Gen.cs, FX_Hex_Gen.cs, & FX_Player.cs.
Set a map width and height in the FX_Map_Gen inspector.
Set the PlayerCamera in the FX_Player inspector
Apply a material to the Material field in the FX_Hex_Gen inspector.
Create a UI canvas and a Text element named “Distance Text”
Run
Setup v1.2.0
Create an empty gameObject and apply the script FX_HexMapGen.js
Apply the Hex prefab to the FX_HexMapGen → Hex Grid
Set the FX_HexMapGen → Map Width Height
Run
Tip:
For non joining maps enable Keep Symetrical. This will keep the edges of the map the same.
While in the unity editor generating a large map 200 x 100 will take a minute to compute. Outside unity in a compiled state this is much faster.
WebPlayer DEMO
This demo shows a grid generated at a size of 20x10 with Keep Symmetrical enabled.
HOT FIX For V1.2.0 Only
Edit the FX_Map_Manager.js and replace the function CalculateDistance() with :
function CalculateDistance(){
var dx : int = Mathf.Abs(GoToHex.x - CurrentHex.x);
var dy : int = Mathf.Abs(GoToHex.y - CurrentHex.y);
var dz : int = Mathf.Abs(GoToHex.z - CurrentHex.z);
var DistA : int = Mathf.Max(dx, dy, dz);
var DistB : int = Mathf.Abs(DistA - Mathf.Abs(MapSize.x + dy));
if(EnableWrapping){
if(dy > DistB){
Distance = Mathf.Min(DistA, dy);
}else{
Distance = Mathf.Min(DistA, DistB);
}
}else{
Distance = DistA;
}
}
Internet Explorer 9 users. If you are having problems downloading files from the fourm please enable Compatibility View
Thanks . The next step is to address the hex grid to an array so it can be accessed by other elements such as an “Ai”. For those who know more than I; should have no problem with this. Right now I’m kinda making it up as I go along.
Distance counting : This new implementation will find the distance from any one Hex to any other Hex on the map.
Changes:
Changed the way hexes are numbered. New system uses a vector3 instead of a vector2.
Hex 0,0,0 is now the bottom left
Updated WebPlayer DEMO
You can click on a Hex to set it as your current position hex and then move the mouse over other hexes to see the distance to that hex. Your starting hex is 0,0,0.
Phew… Creating that distance counter was a new experience, i learned quite a bit about how to use some Mathf functions that i haven’t had the opportunity to use before; even if they are not the ones i ended up using in the code. Much fun was had.
@ g00niebird : Yes. The Vector3 makes distance calculations very easy as it’s now the Max of the Abs value of the difference of x -x or y - y or z - z.
The z you will notice is just a the negative value of x + y with in that cell. X Y are still your position within the grid. Z is only used for distance calculations. I’ll post up a new image demonstrating this a bit later, but i’m off to work right now. You can check out this PAGE for more info.
Hex Map Wrapping - By enabling “Enable Wrapping” you will be able to create a hex map that seams to wrap around its x axis.
Wrapped Hex Map Counting - when “Enable Wrapping” is enabled you will all ways be able to find out how far you are from a desired hex even when wrapping from left to right or right to left.
Able to set initial camera height.
Able to set initial camera angle.
Changes:
Keep Symmetrical will be set to disabled if Enable Wrapping is enabled.
Known issues:
For some reason the camera seams a bit jerky at times. I’m not sure why atm.
Updated WebPlayer DEMO to latest build.
This is a first attempt at creating a wrapping world. It’s not perfect but it’s close enough for a release. This is something i will continue to work on.
Previous Updates
Version 1.1.0
New Features
Distance counting : This new implementation will find the distance from any one Hex to any other Hex on the map.
Changes:
Changed the way hexes are numbered. New system uses a vector3 instead of a vector2.
Hex 0,0,0 is now the bottom left
Version 1.0.3
Changes:
1.Changed the orientation of the Hexagon. This makes counting much easier and the map neater.
Version 1.0.2
New Features:
Keep Symmetrical. This option will keep the edges of the map symmetrical.
This is really great, thanks so much for sharing it!
I’d like to use this in my first Unity project, a hex-based Risk clone. Would I be able to alter the scripts to allow me to manually place hexes in a grid (via the editor)? I’m still catching up on Unity-based development.
@nagata: I don’t see why you couldn’t elevate the hex. Though the hex is just a flat plane, there would be nothing under it. You would have to either bring in your own 3D hex and adjust the vertices for your height. Or make some type of mask to cover up the empty space below the hex. I’m sure there are lots of ways.
As for Ai. Not any time soon. I only created the hex board as an experiment. Mainly to understand how to count hexes. The math to get from one hex to the next is in the code so it should be able to be re-purposed for an Ai. As long as the Ai knows which hex it’s on and what hex it wants to get to. For that you would want to create a table of the hexes that contains its position, land type, and any resources. Then the Ai could look at the table and say “i want to get to hex blah, blah”. You would also want a movement counter to check how many more moves you have.
Hey, excellent work! I prefer this coordinate system for hexes, as it makes things like pathfinding (which I’ve added to this easily!) much simpler.
One question though, assuming you’re still working on this: do you have any suggestions for converting world coordinates (say from a camera->ground plane intersection) to hex coordinates? I’m interested in procedurally generating the hex meshes, or combining the meshes after instantiation and removing the gameobjects/colliders that are currently used for each hex. Having a GO/collider for tens of thousand of hexes just won’t work without a paging/viewport system of some kind, but I’m stuck trying to figure out a formula to do mouse picking without the colliders.
Thanks for any help, would love to see more updates to this project!
@Mingo: I see exactly what your want to do but unfortunately i don’t have an answer for you. I do seam to remember an article i read on the internet while i was searching for a method of counting across hexes. I think the article was using a pixel color look-up for hex position information from a flat plain / texture. I only think that is what the article was about. I didn’t spend too much time reading it, i only thought it was interesting but out of my realm.
One thing you could try would be a way to count to the center of a hex from wold space. If the center of a hex to any other hex is 1 unit then you could convert your X,Y world position to some Hex position.
It would look something like:
World position X=4 Y=0
This would be the fifth Hex to the right of Hex 0,0.
Hex Space = 4,0
You would just need to figure out your vertical offset.
You know that your first row of hexes is starting at 0,0. This makes the first row an even number. Then your second row 0,1 is an Odd number. Your odd row Hexes are off set by from the row above or below them by .5. So you would just need to check if your Y position is odd or even then adjust your Hex count based on this.
It would look something like:
World position X=4.5 Y=2
This would be the fifth Hex to the right on the third row.
Hex Space = 4,2
Remember you are counting starting with 0. Visually 0 + 4 would be the fifth hex, but in an array it’s stored as 4. Remember your array offset for a visual conversion.
This is far from perfect as you would loose accuracy as you get closer to the edge of a hex.
This is just an idea that with some work might be able to work. What ever you choose to do let me know if you get it to work the way you want. I would like to know. GL
There’s probably a much simpler way to translate from hex to world coords and back, but the approach I’m taking for now is to plot a line in world space from hex[0,0] to hex[0, maxY] to simulate the hex Y axis. I then find the closest point on this line to the mouse cursor’s world position. This gives me the Y coordinate in hex space. The distance of the point from the line gives me the hex X coordinate.
Topcoder for more info on it, especially “Line-Point Distance” algorithm on the page.
Could you explain in full how to apply this thing? Your setup isn’t very clear on how to get the grid work. All I’ve got is one hex and when I try to get the game to play to test the hex out the game just keeps pausing. I can’t find FX_Hex_Map_Gen or whatever.
This is amazing. Thanks for the great work. I only just started working with unity, but this will help a lot. Cheers.
Quick question tho. Following just the instructions above and setting my Map size to 10,10 the distance calculation does not remain accurate. It seems to assume that Setting the active tile to 0,0,0 then moving your mouse across to 5,0,-5 measures a distance of 5, but moving any further across lowers the distance until at 9,0,-9 it assumes the distance is 1. It’s like it is assuming it can wrap back around from 9,0,-9 to 0,0,0. I can get around that by simply creating my own distance measurement method, but I was just wondering why your default behavior acted in this way. (Note: I have Enable Wrapping and Keep Symmetrical both off).