74 lines
3.3 KiB
C#
74 lines
3.3 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using UnityEngine;
|
|
using Object = UnityEngine.Object;
|
|
|
|
namespace Grid {
|
|
public class GridSystemHex<TGridObject> {
|
|
private const float hexVerticalOffsetMultiplier = .75f;
|
|
private readonly float cellSize;
|
|
private readonly TGridObject[,] gridObjectArray;
|
|
|
|
public GridSystemHex(int width, int height, float cellSize, Func<GridSystemHex<TGridObject>, 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<GridPosition> 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.Where(neighbourGridPosition => 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>();
|
|
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;
|
|
}
|
|
} |