//BEGIN PATHFINDING Инициализация при клике на клетку (используется в MG_KeyboardMouseControl) public void InitCellForPathfinding(MG_hexagonCell selected_compCell) { if (GetComponent <MG_PathfindingModeGUI>().CheckBox_A_point) { SetCell_StartPoint(selected_compCell); //Режим: Установить Стартовую точку } if (GetComponent <MG_PathfindingModeGUI>().CheckBox_B_point) { SetCell_TargetPoint(selected_compCell); //Режим: Установить Цель точку } }
private Collection <MG_AP_PathNode> GetNeighbours(MG_AP_PathNode pathNode, MG_hexagonCell goal) { Step++; var result = new Collection <MG_AP_PathNode>(); // Соседними точками являются соседние по стороне клетки. MG_hexagonCell[] neighbourPoints = new MG_hexagonCell[6]; neighbourPoints[0] = pathNode.Current_compCell.NeighbourArray[0]; neighbourPoints[1] = pathNode.Current_compCell.NeighbourArray[1]; neighbourPoints[2] = pathNode.Current_compCell.NeighbourArray[2]; neighbourPoints[3] = pathNode.Current_compCell.NeighbourArray[3]; neighbourPoints[4] = pathNode.Current_compCell.NeighbourArray[4]; neighbourPoints[5] = pathNode.Current_compCell.NeighbourArray[5]; foreach (var neighbour in neighbourPoints) { if (!neighbour)//если существует соседняя клетка { continue; } if (!neighbour.Walkable)//если можно ходить по ней { continue; } // Заполняем данные для точки маршрута. TotalVisitedCells++; if (TotalVisitedCells == TotalCellcount)//если слишком много шагов, то перестать искать! { continue; } GameObject obj_pathNode = Instantiate(Prefab_pathNode); //Создание нода obj_pathNode.transform.parent = this.transform; //Вставляем данный child в Parent obj_pathNode.name = "Pathnode №" + TotalVisitedCells + ": (" + neighbour.GameCoordinate_x + ", " + neighbour.GameCoordinate_y + ")"; //Задаем имя объекту MG_AP_PathNode neighbourNode = obj_pathNode.GetComponent <MG_AP_PathNode>(); ArrayOfNodes[TotalVisitedCells] = neighbourNode;//кладем в массив neighbourNode.Position = neighbour.transform; neighbourNode.CameFrom = pathNode; neighbourNode.PathLengthFromStart = pathNode.PathLengthFromStart + 1;// neighbourNode.GetDistanceBetweenNeighbours(); neighbourNode.HeuristicEstimatePathLength = GetHeuristicPathLength(neighbour, goal); neighbourNode.Current_compCell = neighbour; result.Add(neighbourNode); neighbour.Rend.material.color = Color.magenta; //neighbour.Label.text = "" + Step + ""; } return(result); }
public void ButtonPressed_Start() { //GetComponent<MG_Pathfinding>().Start_Pathfinding(); //OLD MG_hexagonCell start = GetComponent <MG_Pathfinding>().Comp_StartCell; MG_hexagonCell end = GetComponent <MG_Pathfinding>().Comp_TargetCell; if (start && end) { List <MG_hexagonCell> way = GetComponent <MG_AP_Pathfinding>().FindPath(start, end); } else { Debug.LogWarning("ButtonPressed_Start(): Не задана начальная или контрольная точка!"); } }
//END PATHFINDING Назначаем начальную точку //BEGIN PATHFINDING Назначаем начальную точку public void SetCell_TargetPoint(MG_hexagonCell selected_compCell) { //BEGIN предыдущую цель нужно перекрасить в обычный цвет MG_hexagonCell comp_previousTargetCell = GetComponent <MG_Pathfinding>().Comp_TargetCell;// берем предыдущий заданный объект цели if (comp_previousTargetCell) { comp_previousTargetCell.GetComponent <MG_hexagonCell>().CancelSelect();// если предыдущий объект был задан, то нужно ресетнуть цвет. //obj_previousTargetCell.GetComponent<MG_hexagonCell>().IsSelectedByMouse = false;// Чтобы можно было перекрасить при заходе мышкой } //END предыдущую цель нужно перекрасить в обычный цвет selected_compCell.GetComponent <MG_hexagonCell>().IsSelectedByMouse = true; //Кликнута мышкой, иначе цвет при наведении перезальется selected_compCell.GetComponent <MG_hexagonCell>().Rend.material.color = new Color(0.2F, 0.3F, 0.4F); //ORANGE Задаем новый цвет клетки цели selected_compCell.Walkable = true; GetComponent <MG_Pathfinding>().Comp_TargetCell = selected_compCell; //Задаем скрипту MG_Pathfinding объект цели }
private float GetHeuristicPathLength(MG_hexagonCell from, MG_hexagonCell to) { return(Math.Abs(from.transform.position.x - to.transform.position.x) + Math.Abs(from.transform.position.y - to.transform.position.y)); }
public List <MG_hexagonCell> FindPath(MG_hexagonCell start, MG_hexagonCell goal) { //Шаг 0. ПОДГОТОВКА RemoveAllNodes(); // Шаг 1. Debug.Log("FindPath(): Шаг 1."); var closedSet = new Collection <MG_AP_PathNode>(); var openSet = new Collection <MG_AP_PathNode>(); TotalVisitedCells = 0; Step = 0; // Шаг 2. Debug.Log("FindPath(): Шаг 2."); GameObject obj_pathNode = Instantiate(Prefab_pathNode); //Создание нода obj_pathNode.transform.parent = this.transform; //Вставляем данный child в Parent obj_pathNode.name = "Pathnode №" + TotalVisitedCells + ": (" + start.GameCoordinate_x + ", " + start.GameCoordinate_y + ")"; //Задаем имя объекту MG_AP_PathNode startNode = obj_pathNode.GetComponent <MG_AP_PathNode>(); start.Label.text = "" + Step + ""; ArrayOfNodes[TotalVisitedCells] = startNode;//кладем в массив startNode.Position = start.transform; startNode.CameFrom = null; startNode.PathLengthFromStart = 0; startNode.HeuristicEstimatePathLength = GetHeuristicPathLength(start, goal); startNode.Current_compCell = start; openSet.Add(startNode); while (openSet.Count > 0) { // Шаг 3. Debug.Log("FindPath(): Шаг 3."); var currentNode = openSet.OrderBy(node => node.EstimateFullPathLength).First(); // Шаг 4. Debug.Log("FindPath(): Шаг 4."); if (currentNode.Current_compCell == goal) { List <MG_hexagonCell> listOfCells = GetPathForNode(currentNode); ReColorPatch(listOfCells); start.Rend.material.color = Color.green; goal.Rend.material.color = new Color(0.2F, 0.3F, 0.4F); start.Label.text = "->BEGIN<-"; goal.Label.text = "->GOAL<-"; return(listOfCells); } // Шаг 5. Debug.Log("FindPath(): Шаг 5."); openSet.Remove(currentNode); closedSet.Add(currentNode); // Шаг 6. Debug.Log("FindPath(): Шаг 6."); foreach (var neighbourNode in GetNeighbours(currentNode, goal)) { // Шаг 7. Debug.Log("FindPath(): Шаг 7."); if (closedSet.Count(node => node.Position == neighbourNode.Position) > 0) { continue; } var openNode = openSet.FirstOrDefault(node => node.Position == neighbourNode.Position); // Шаг 8. Debug.Log("FindPath(): Шаг 8."); if (openNode == null) { openSet.Add(neighbourNode); } else if (openNode.PathLengthFromStart > neighbourNode.PathLengthFromStart) { // Шаг 9. Debug.Log("FindPath(): Шаг 9."); openNode.CameFrom = currentNode; openNode.PathLengthFromStart = neighbourNode.PathLengthFromStart; } } } // Шаг 10. Debug.LogWarning("FindPath(): Шаг 10. Путь не найден!"); return(null); }
//END Используется в MG_KeyboardMouseControl для изменения цвета клетки после клика public void SetNeigbrours() { NeighbourArray = new MG_hexagonCell[6]; int x_plus = gameCoordinate_x + 1; int x_minus = gameCoordinate_x - 1; int y_plus = gameCoordinate_y + 1; int y_minus = gameCoordinate_y - 1; bool NotoutOfRange_x_plus = (GridCell.X > x_plus); bool NotoutOfRange_x_minus = (0 <= x_minus); bool NotoutOfRange_y_plus = (GridCell.Y > y_plus); bool NotoutOfRange_y_minus = (0 <= y_minus); if (FlatTopped) { if (CoordStyle_isVar1) { if (NotoutOfRange_x_minus) { NeighbourArray[0] = GridCell.ArrayOfCells_2D[gameCoordinate_x - 1, gameCoordinate_y]; } if (NotoutOfRange_x_minus && NotoutOfRange_y_plus) { NeighbourArray[1] = GridCell.ArrayOfCells_2D[gameCoordinate_x - 1, gameCoordinate_y + 1]; } if (NotoutOfRange_y_plus) { NeighbourArray[2] = GridCell.ArrayOfCells_2D[gameCoordinate_x, gameCoordinate_y + 1]; } if (NotoutOfRange_x_plus) { NeighbourArray[3] = GridCell.ArrayOfCells_2D[gameCoordinate_x + 1, gameCoordinate_y]; } if (NotoutOfRange_y_minus) { NeighbourArray[4] = GridCell.ArrayOfCells_2D[gameCoordinate_x, gameCoordinate_y - 1]; } if (NotoutOfRange_x_minus && NotoutOfRange_y_minus) { NeighbourArray[5] = GridCell.ArrayOfCells_2D[gameCoordinate_x - 1, gameCoordinate_y - 1]; } } else { if (NotoutOfRange_x_minus) { NeighbourArray[0] = GridCell.ArrayOfCells_2D[gameCoordinate_x - 1, gameCoordinate_y]; } if (NotoutOfRange_y_plus) { NeighbourArray[1] = GridCell.ArrayOfCells_2D[gameCoordinate_x, gameCoordinate_y + 1]; } if (NotoutOfRange_x_plus && NotoutOfRange_y_plus) { NeighbourArray[2] = GridCell.ArrayOfCells_2D[gameCoordinate_x + 1, gameCoordinate_y + 1]; } if (NotoutOfRange_x_plus) { NeighbourArray[3] = GridCell.ArrayOfCells_2D[gameCoordinate_x + 1, gameCoordinate_y]; } if (NotoutOfRange_x_plus && NotoutOfRange_y_minus) { NeighbourArray[4] = GridCell.ArrayOfCells_2D[gameCoordinate_x + 1, gameCoordinate_y - 1]; } if (NotoutOfRange_y_minus) { NeighbourArray[5] = GridCell.ArrayOfCells_2D[gameCoordinate_x, gameCoordinate_y - 1]; } } } else { if (CoordStyle_isVar1) { if (NotoutOfRange_x_minus && NotoutOfRange_y_minus) { NeighbourArray[0] = GridCell.ArrayOfCells_2D[gameCoordinate_x - 1, gameCoordinate_y - 1]; } if (NotoutOfRange_x_minus) { NeighbourArray[1] = GridCell.ArrayOfCells_2D[gameCoordinate_x - 1, gameCoordinate_y]; } if (NotoutOfRange_y_plus) { NeighbourArray[2] = GridCell.ArrayOfCells_2D[gameCoordinate_x, gameCoordinate_y + 1]; } if (NotoutOfRange_x_plus) { NeighbourArray[3] = GridCell.ArrayOfCells_2D[gameCoordinate_x + 1, gameCoordinate_y]; } if (NotoutOfRange_x_plus && NotoutOfRange_y_minus) { NeighbourArray[4] = GridCell.ArrayOfCells_2D[gameCoordinate_x + 1, gameCoordinate_y - 1]; } if (NotoutOfRange_y_minus) { NeighbourArray[5] = GridCell.ArrayOfCells_2D[gameCoordinate_x, gameCoordinate_y - 1]; } } else { if (NotoutOfRange_x_minus) { NeighbourArray[0] = GridCell.ArrayOfCells_2D[gameCoordinate_x - 1, gameCoordinate_y]; } if (NotoutOfRange_x_minus && NotoutOfRange_y_plus) { NeighbourArray[1] = GridCell.ArrayOfCells_2D[gameCoordinate_x - 1, gameCoordinate_y + 1]; } if (NotoutOfRange_y_plus) { NeighbourArray[2] = GridCell.ArrayOfCells_2D[gameCoordinate_x, gameCoordinate_y + 1]; } if (NotoutOfRange_x_plus && NotoutOfRange_y_plus) { NeighbourArray[3] = GridCell.ArrayOfCells_2D[gameCoordinate_x + 1, gameCoordinate_y + 1]; } if (NotoutOfRange_x_plus) { NeighbourArray[4] = GridCell.ArrayOfCells_2D[gameCoordinate_x + 1, gameCoordinate_y]; } if (NotoutOfRange_y_minus) { NeighbourArray[5] = GridCell.ArrayOfCells_2D[gameCoordinate_x, gameCoordinate_y - 1]; } } } }
//BEGIN ДЛЯ ТЕСТА, ЧТОБЫ ПЕРЕСОЗДАТЬ КАРТУ И ПОЛУЧИТЬ НЕ ПУСТЫЕ ПЕРЕМЕННЫЕ. public void GenerateGrid() //Создано для одного типа Hexagonal cell: Pointy Topped (другой Flat Topped возможен!) { GridCanvas = GetComponentInChildren <Canvas>(); //Canvas для текста float x_Pos = 0; //Позиция по горизонтали для новой клетки float y_Pos = 0; //Позиция по вертикали для новой клетки int xy_fixer = 0; //Коррекция для правильной Hexagon карты (Значение: 0-1), чтобы выглядила как квадратная карта. //BEGIN Если выбран тип карты FlatToppe if (FlatTopped) { SelectedHexagonPrefab = HexFlatToppe; } else { SelectedHexagonPrefab = HexPointyTopped; } //END Если выбран тип карты FlatToppe, а не PointyTopped ArrayOfCells_2D = new MG_hexagonCell[Y, X]; //BEGIN Default настрйоки для изменения типа карты, иначе будут глюки this.transform.eulerAngles = new Vector3(0, 0, 0); this.transform.position = new Vector3(0, 0, 0); //END Default настрйоки для изменения типа карты, иначе будут глюки for (int i = 0; i < Y; i++) { if (FlatTopped) { x_Pos = 0; //Для создания правильной квадратной карты с Hex y_Pos = 0 + (-5f) * (i - 1); // + (-5f) * (i - 1);//(y_Pos + - 5f) * (i-1);//Для создания правильной квадратной карты с Hex (след строка) xy_fixer = 0; } else { x_Pos = 2.5f * xy_fixer; //Для создания правильной квадратной карты с Hex y_Pos = 4.25f * i * (-1); //Для создания правильной квадратной карты с Hex (след строка) } for (int j = 0; j < X; j++) { this.transform.localScale = new Vector3(1, 1, 1);//Scale самой карты (можно поменять в конце метода если необходимо) //BEGIN Создание клетки объекта и его настройка GameObject hexagon = Instantiate(SelectedHexagonPrefab); //Создание самой клетки ArrayOfCells_2D[i, j] = hexagon.GetComponent <MG_hexagonCell>(); //кладем в массив hexagon.transform.parent = this.transform; //Вставляем данный child в Parent hexagon.transform.position = new Vector3(x_Pos, y_Pos, 0); //позиция клетки на карте hexagon.transform.localScale = new Vector3(1, 1, 1); //масштаб клетки hexagon.GetComponent <MG_hexagonCell>().GameCoordinate_x = i; //Задаем игровую координату по X hexagon.GetComponent <MG_hexagonCell>().GameCoordinate_y = j; //Задаем игровую координату по Y hexagon.GetComponent <MG_hexagonCell>().EditorCoordinate = hexagon.transform.position; //Задаем реальную позицию в редакторе hexagon.GetComponent <MG_hexagonCell>().GridCell = this; //Назначаем саму карту hexagon.GetComponent <MG_hexagonCell>().FlatTopped = FlatTopped; //Вид Hexagon hexagon.GetComponent <MG_hexagonCell>().Walkable = true; //Можно ли ходить (для PATHFINDING) 08.03.2018 hexagon.name = "Hexagon (" + i + ", " + j + ")"; //Задаем имя объекту //-Для лучшего способа получение соседей, чтобы не перепрыгивать через соседа (тот самый баг для Хексагонов). if (xy_fixer == 0) { hexagon.GetComponent <MG_hexagonCell>().CoordStyle_isVar1 = true; } else { hexagon.GetComponent <MG_hexagonCell>().CoordStyle_isVar1 = false; } //-end //END Создание клетки объекта и его настройка //BEGIN Метка координатная на клетке Text label = Instantiate <Text>(CellLabelPrefab); //Создание самой метки label.rectTransform.SetParent(GridCanvas.transform, false); //Задаем Parent label.rectTransform.anchoredPosition = //Задаем позицию new Vector2(x_Pos, y_Pos); label.text = i + ", " + j; //Задаем текст hexagon.GetComponent <MG_hexagonCell>().Label = label; //Задаем клетки данный текст в память для будущей интеракции label.name = "Label (" + i + ", " + j + ")"; //Задаем имя объекту //END Метка координатная на клетке if (FlatTopped) { x_Pos += 4.25f;//Корректировка для следующей клетки if (xy_fixer == 0) { y_Pos += -2.49f;//Корректировка для следующей клетки xy_fixer = 1; } else { y_Pos += 2.49f;//Корректировка для следующей клетки xy_fixer = 0; } } else { x_Pos += 5f;//Корректировка для следующей клетки } //hexagon.GetComponent<Hexagon>().OffsetCoord = new Vector2(0, 0); } //BEGIN Специальная коррекция для Hexagon карты, чтобы выглядила как квадратная карта if (FlatTopped) { // y_Pos += -5f; } else { if (xy_fixer == 0) { xy_fixer = 1; } else { xy_fixer = 0; } } //END Специальная коррекция для Hexagon карты, чтобы выглядила как квадратная карта } SetAllNeigbroursForAllCell();//Для установки соседей для всех клеток после генерации карты }