Загрузка данных
public class InfoflowGridGraph : MonoBehaviour
{
/// <summary>
/// Grid
/// </summary>
[SerializeField]
private int width = 10;
[SerializeField]
private int depth = 10;
[SerializeField]
private float cellSize = 1f;
[SerializeField]
private LayerMask obstacleLayerMask;
[SerializeField]
private float verticalOffset;
[SerializeField]
private int offsetForXYPlane;
private Bounds rootBounds;
private GridNode[,] nodes;
public bool debugDrawCell;
private int zDepth;
private int yDepth;
/// <summary>
/// Flow path
/// </summary>
[SerializeField]
private List<Transform> sourceModules;
[SerializeField]
private List<Transform> targetModules;
private List<Vector3> commonPath;
[SerializeField]
private float zTolerance = 0.01f;
private Dictionary<float, List<Transform>> GroupModulesByZRows()
{
var rows = new Dictionary<float, List<Transform>>();
foreach (var module in sourceModules)
{
if (module == null)
continue;
float moduleZ = module.position.z;
bool addedToRow = false;
foreach (var row in rows)
{
if (Mathf.Abs(moduleZ - row.Key) <= zTolerance)
{
row.Value.Add(module);
addedToRow = true;
break;
}
}
if (!addedToRow)
rows[moduleZ] = new List<Transform> {module};
}
return rows;
}
[Button()]
public void CreateGrid()
{
rootBounds = ObjectToFrustumFitter.GetBoundsWithChildren(gameObject);
float height = rootBounds.size.y - (transform.position.y - rootBounds.min.y);
width = Mathf.RoundToInt(rootBounds.size.x / cellSize);
zDepth = Mathf.RoundToInt(rootBounds.size.z / cellSize);
yDepth = Mathf.RoundToInt(height / cellSize);
depth = zDepth + yDepth;
nodes = new GridNode[width, depth];
for (int x = 0; x < width; x++)
{
for (int z = 0; z < depth; z++)
{
Vector3 worldPos = GetWorldPosition(x, z);
bool isWalkable = !Physics.CheckBox(worldPos, Vector3.one * cellSize * 0.5f, Quaternion.identity,
obstacleLayerMask);
nodes[x, z] = new GridNode(x, z, isWalkable);
}
}
}
public GridNode GetNode(int x, int z)
{
if (x < 0 || x >= width)
return null;
if (z < 0 || z >= depth)
return null;
return nodes[x, z];
}
public GridNode GetNodeFromWorldPosition(Vector3 worldPosition)
{
Vector3 localPos = worldPosition - new Vector3(rootBounds.min.x, 0, rootBounds.min.z);
int x = Mathf.FloorToInt(localPos.x / cellSize);
int z = Mathf.FloorToInt(localPos.z / cellSize);
if (x < 0 || x >= width || z < 0 || z >= depth)
return null;
return nodes[x, z];
}
public Vector3 GetWorldPosition(int x, int z)
{
float cellExtents = cellSize * 0.5f;
Vector3 starPosition = new Vector3(
rootBounds.min.x + cellExtents,
transform.position.y + verticalOffset,
rootBounds.min.z + cellExtents);
if (z >= zDepth)
{
return starPosition + new Vector3(x * cellSize, (z - zDepth) * cellSize,
(zDepth + offsetForXYPlane) * cellSize);
}
else
{
return starPosition + new Vector3(x * cellSize, 0, z * cellSize);
}
}
public List<GridNode> GetNeighbours(GridNode node)
{
List<GridNode> neighbours = new List<GridNode>();
TryAddNeighbours(neighbours, node.X + 1, node.Z);
TryAddNeighbours(neighbours, node.X - 1, node.Z);
TryAddNeighbours(neighbours, node.X, node.Z + 1);
TryAddNeighbours(neighbours, node.X, node.Z - 1);
return neighbours;
}
private void TryAddNeighbours(List<GridNode> neighbours, int x, int z)
{
GridNode neighbour = GetNode(x, z);
if (neighbour == null)
return;
if (neighbour.IsWalkable == false)
return;
neighbours.Add(neighbour);
}
private void OnDrawGizmos()
{
if (nodes == null)
return;
if (debugDrawCell)
{
for (int x = 0; x < width; x++)
{
for (int z = 0; z < depth; z++)
{
GridNode node = nodes[x, z];
Gizmos.color = node.IsWalkable ? Color.white : Color.red;
if (z >= zDepth)
{
Gizmos.DrawWireCube(GetWorldPosition(x, z), new Vector3(cellSize, cellSize, 0));
}
else
{
Gizmos.DrawWireCube(GetWorldPosition(x, z), new Vector3(cellSize, 0, cellSize));
}
}
}
foreach (var vector3 in commonPath)
{
Gizmos.color = Color.green;
Gizmos.DrawSphere(vector3, cellSize * 0.2f);
}
}
}
}