## Friday, December 17, 2010

### Unity3D Hex Grid.

How to snap world points to the closest hexagonal grid point, where a hexagonal grid point is the center of the hexagon. The Init(size) parameter is the length of one edge of the hexagon.

`using UnityEngine;using System.Collections;public class HexGridSnap : MonoBehaviour {   static float size,h,r,b,a;  static void Init (float size) {  HexGridSnap.size = size;  h = Mathf.Sin(30*Mathf.Deg2Rad) * size;  r = Mathf.Cos(30*Mathf.Deg2Rad) * size;  b = size + 2 * h;  a = 2 * r; }  static Vector3 Snap(Vector3 p) {  var u = p.x;  var v = p.z;  var x = u - u % a + r;  var y = v - v % b + ((x - r) / a % 1) * b / 2;  return new Vector3(x, p.y, y); }}`

Jonas said...

using UnityEngine;

using System.Collections;

/*

* HexGridSnap by Simon Wittber from entitycrisis.blogspot.com

*

* adapted to C# by Jonas Widmer, frinx.ch (I had to change the modulo for the indentTrigger, line 30, to 2 instead of 1 ... )

*

* for hexagon standing on a point not an edge

*/

public class HexGridSnap : MonoBehaviour

{

static float size,h,r,b,a;

public static void Init (float size)

{

HexGridSnap.size = size;

HexGridSnap.b = size * 2f;

HexGridSnap.a = 2f * r;

}

public static Vector3 SnapCenter(Vector3 p)

{

float u = p.x;

float v = p.z;

float x = u - u % HexGridSnap.a + HexGridSnap.r;

float indentTrigger = ((x - HexGridSnap.r) / HexGridSnap.a % 2);

//print("indent Trigger is "+indentTrigger);

float y = v - v % HexGridSnap.b + indentTrigger * (HexGridSnap.b / 2f);

return new Vector3(x, p.y, y);

}

public static Vector3 SnapEdge(Vector3 p)

{

Vector3 c = SnapCenter(p);

Vector3[] g = new Vector3;

//

g = new Vector3(HexGridSnap.r, 0, -HexGridSnap.h) + c; //right top

g = new Vector3(HexGridSnap.r, 0, HexGridSnap.h) + c; //right lower

g = new Vector3(0, 0, HexGridSnap.size) + c; //bottom point

g = new Vector3(-HexGridSnap.r,0, HexGridSnap.h) + c; //left lower

g = new Vector3(-HexGridSnap.r,0, -HexGridSnap.h) + c; //left upper

g = new Vector3(0, 0, -HexGridSnap.size) + c; //top point

int closest = 0;

float closestDist = Vector3.SqrMagnitude(g - p);

for(int i = 1; i < g.Length; i++)

{

if(Vector3.SqrMagnitude(g[i] - p) < closestDist)

{

closestDist = Vector3.SqrMagnitude(g[i] - p);

closest = i;

}

}

//print("snapping to point "+closest);

return g[closest];

}

}

Jonas said...

okay that was hasty. I wanted to add some flexibility but it doesn't work like this.