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);
}

}

2 comments:

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.h = Mathf.Sin(30f*Mathf.Deg2Rad) * size;

HexGridSnap.r = Mathf.Cos(30f*Mathf.Deg2Rad) * 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[6];



//

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

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

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

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

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

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



int closest = 0;

float closestDist = Vector3.SqrMagnitude(g[0] - 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.

Popular Posts