using System; using System.Collections.Generic; using UnityEngine; using Object = UnityEngine.Object; namespace Grid { public class GridSystemHex { private const float hexVerticalOffsetMultiplier = .75f; private readonly float cellSize; private readonly TGridObject[,] gridObjectArray; public GridSystemHex(int width, int height, float cellSize, Func, GridPosition, TGridObject> createGridObject) { Width = width; Height = height; this.cellSize = cellSize; gridObjectArray = new TGridObject[width, height]; for (int x = 0; x < width; x++) { for (int z = 0; z < height; z++) { gridObjectArray[x, z] = createGridObject(this, new(x, z)); } } } public int Height { get; } public int Width { get; } public Vector3 GetWorldPosition(GridPosition gridPosition) { return new Vector3(gridPosition.X, 0, 0) * cellSize + cellSize * hexVerticalOffsetMultiplier * new Vector3(0, 0, gridPosition.Z) + (gridPosition.Z % 2 == 1 ? cellSize * .5f * Vector3.right : Vector3.zero); } public GridPosition GetGridPosition(Vector3 worldPosition) { //Get the rough GridPosition GridPosition roughXZ = new(Mathf.RoundToInt(worldPosition.x / cellSize), Mathf.RoundToInt(worldPosition.z / cellSize / hexVerticalOffsetMultiplier)); //Get all neighbours bool oddRow = roughXZ.Z % 2 == 1; List neighbourGridPositionList = new() { roughXZ + new GridPosition(-1, 0), roughXZ + new GridPosition(+1, 0), roughXZ + new GridPosition(0, +1), roughXZ + new GridPosition(0, -1), roughXZ + new GridPosition(oddRow ? +1 : -1, +1), roughXZ + new GridPosition(oddRow ? +1 : -1, -1), }; //Find the closest neighbour GridPosition closestGridPosition = roughXZ; foreach (GridPosition neighbourGridPosition in neighbourGridPositionList) { if (Vector3.Distance(worldPosition, GetWorldPosition(neighbourGridPosition)) < Vector3.Distance(worldPosition, GetWorldPosition(closestGridPosition))) closestGridPosition = neighbourGridPosition; } return closestGridPosition; } public void CreateDebugObjects(Transform debugPrefab) { for (int x = 0; x < Width; x++) { for (int z = 0; z < Height; z++) { GridPosition gridPosition = new(x, z); Transform debugTransform = Object.Instantiate(debugPrefab, GetWorldPosition(gridPosition), Quaternion.identity); GridDebugObject gridDebugObject = debugTransform.GetComponent(); gridDebugObject.SetGridObject(GetGridObject(gridPosition)); } } } public TGridObject GetGridObject(GridPosition gridPosition) => gridObjectArray[gridPosition.X, gridPosition.Z]; public bool IsValidGridPosition(GridPosition gridPosition) => gridPosition is { X: >= 0, Z: >= 0 } && gridPosition.X < Width && gridPosition.Z < Height; } }