Created
January 14, 2025 11:17
-
-
Save GeorgiyRyaposov/d8559af4b25491bde352a40e6f6ae684 to your computer and use it in GitHub Desktop.
Simple square grid: converts position to index; keep flat list of grid items
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Unity.Burst; | |
using Unity.Mathematics; | |
using UnityEngine; | |
using UnityEngine.Events; | |
namespace Grids.Square | |
{ | |
[BurstCompile] | |
public class SquareGrid<T> | |
{ | |
private readonly UnityEvent<OnValueChangedArgs> _onValueChanged = new (); | |
public class OnValueChangedArgs | |
{ | |
public int X; | |
public int Y; | |
} | |
private readonly int _width; | |
private readonly int _height; | |
private readonly T[] _cells; | |
private readonly IIndexesHelper _indexesHelper; | |
private readonly float3 _originPosition; | |
private readonly float _cellSize; | |
public int Width => _width; | |
public int Height => _height; | |
public float3 OriginPosition => _originPosition; | |
public float CellSize => _cellSize; | |
public SquareGrid(int width, int height, float cellSize, float3 originPosition, System.Func<SquareGrid<T>, int, int, T> createCell, bool xzPlane = true) | |
{ | |
_width = width; | |
_height = height; | |
_originPosition = originPosition; | |
_cellSize = cellSize; | |
_cells = new T[width * height]; | |
_indexesHelper = xzPlane | |
? new IndexesHelperXZ(cellSize, originPosition) | |
: new IndexesHelperXY(cellSize, originPosition); | |
for (int x = 0; x < width; x++) | |
{ | |
for (int y = 0; y < height; y++) | |
{ | |
var index = x + y * _width; | |
_cells[index] = createCell(this, x, y); | |
} | |
} | |
} | |
public float3 GetWorldPosition(int x, int y) | |
{ | |
return _indexesHelper.GetWorldPosition(x, y); | |
} | |
public int2 GetIndexes(float3 worldPos) | |
{ | |
return _indexesHelper.GetCellIndex(worldPos); | |
} | |
public void SetValue(float3 worldPos, T value) | |
{ | |
var indexes = GetIndexes(worldPos); | |
SetValue(indexes.x, indexes.y, value); | |
} | |
public void SetValue(int x, int y, T value) | |
{ | |
var index = x + y * _width; | |
if (index < _cells.Length) | |
{ | |
_cells[index] = value; | |
TriggerOnValueChanged(x, y); | |
} | |
else | |
{ | |
Debug.LogError($"Index out of range : {index} ({x}:{y})"); | |
} | |
} | |
public T GetValue(float3 worldPos) | |
{ | |
var indexes = GetIndexes(worldPos); | |
return GetValue(indexes.x, indexes.y); | |
} | |
public T GetValue(int x, int y) | |
{ | |
var index = x + y * _width; | |
return index < _cells.Length ? _cells[index] : default; | |
} | |
public void TriggerOnValueChanged(int x, int y) | |
{ | |
_onValueChanged.Invoke(new OnValueChangedArgs() {X = x, Y = y}); | |
} | |
public void SubscribeOnValueChanged(UnityAction<OnValueChangedArgs> action) | |
{ | |
_onValueChanged.AddListener(action); | |
} | |
public void UnsubscribeOnValueChanged(UnityAction<OnValueChangedArgs> action) | |
{ | |
_onValueChanged.RemoveListener(action); | |
} | |
[BurstCompile] | |
public void DrawGridDebug() | |
{ | |
var mapWidth = _width; | |
var mapHeight = _height; | |
var color = Color.white; | |
for (int x = 0; x < mapWidth; x++) | |
{ | |
for (int y = 0; y < mapHeight; y++) | |
{ | |
DrawCell(x, y, color); | |
} | |
} | |
Debug.DrawLine(GetWorldPosition(0, mapHeight), GetWorldPosition(mapWidth, mapHeight), color, 100f); | |
Debug.DrawLine(GetWorldPosition(mapWidth, 0), GetWorldPosition(mapWidth, mapHeight), color, 100f); | |
} | |
private void DrawCell(int x, int y, Color color) | |
{ | |
Debug.DrawLine(GetWorldPosition(x, y), GetWorldPosition(x, y + 1), color, 100f); | |
Debug.DrawLine(GetWorldPosition(x, y), GetWorldPosition(x + 1, y), color, 100f); | |
} | |
#region IndexesHelper | |
private interface IIndexesHelper | |
{ | |
float3 GetWorldPosition(int x, int y); | |
int2 GetCellIndex(float3 worldPos); | |
} | |
private class IndexesHelperXZ : IIndexesHelper | |
{ | |
private readonly float _cellSize; | |
private readonly float3 _originPosition; | |
public IndexesHelperXZ(float cellSize, float3 originPosition) | |
{ | |
_cellSize = cellSize; | |
_originPosition = originPosition; | |
} | |
public float3 GetWorldPosition(int x, int y) | |
{ | |
return new float3(x, 0, y) * _cellSize + _originPosition; | |
} | |
public int2 GetCellIndex(float3 worldPos) | |
{ | |
return SquareGridCellUtil.GetCellIndexXZ(worldPos, _originPosition, _cellSize); | |
} | |
} | |
private class IndexesHelperXY : IIndexesHelper | |
{ | |
private readonly float _cellSize; | |
private readonly float3 _originPosition; | |
public IndexesHelperXY(float cellSize, float3 originPosition) | |
{ | |
_cellSize = cellSize; | |
_originPosition = originPosition; | |
} | |
public float3 GetWorldPosition(int x, int y) | |
{ | |
return new float3(x, y, 0) * _cellSize + _originPosition; | |
} | |
public int2 GetCellIndex(float3 worldPos) | |
{ | |
return SquareGridCellUtil.GetCellIndexXY(worldPos, _originPosition, _cellSize); | |
} | |
} | |
#endregion //IndexesHelper | |
} | |
public static class SquareGridCellUtil | |
{ | |
public static int2 GetCellIndexXY(float3 worldPos, float3 gridOriginPos, float gridCellSize) | |
{ | |
var pos = worldPos - gridOriginPos; | |
return new int2((int) math.floor(pos.x / gridCellSize), | |
(int) math.floor(pos.y / gridCellSize)); | |
} | |
public static int2 GetCellIndexXZ(float3 worldPos, float3 gridOriginPos, float gridCellSize) | |
{ | |
var pos = worldPos - gridOriginPos; | |
return new int2((int) math.floor(pos.x / gridCellSize), | |
(int) math.floor(pos.z / gridCellSize)); | |
} | |
public static int CalculateIndex(int x, int y, int gridWidth) | |
{ | |
return x + y * gridWidth; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment