Загрузка данных


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