3

Нужна подобная сетка из правильных шестиугольников (в форме сот):

Сетка

Я написал код, который генерирует следующую неверную сетку:

Моя сетка

Мой код:

    [ContextMenu("Generate grid")]
    public void GenerateGrid()
    {
        for(int x = 0; x < _gridSize.x; x++)
        {
            for (int z = 0; z < _gridSize.z; z++)
            {
                var meshSize = _cell.GetComponent<MeshRenderer>().bounds.size;
                var position = new Vector3(x * (meshSize.x + _offset), 0, z * (meshSize.z + _offset));
            var cell = Instantiate(_cell, position, Quaternion.Euler(_rotationOffset), _parent.transform);

            cell.Position = new Vector2(x, z);
            cell.name = $&quot;Cell: x:{x}, z:{z}&quot;;

            GridActions.AllCell.Add(cell);
        }
    }
}

Как генерировать именно сетку с первого скриншота?

  • данный вопрос в виде картинки следует закрыть, потому что он бесполезен для базы знаний (тот, у кого возникнет подобный вопрос, не сможет найти данный вопрос и ответы к нему) – aleksandr barakin Aug 21 '21 at 06:34
  • @aleksandrbarakin Думаю, после редактирования вопрос выглядит нормально. – Максим Фисман Aug 21 '21 at 10:24

1 Answers1

3

Основные простые расчеты приведены на чертеже, я лишь запишу получившиеся данные:
AB=sqrt(3)/2
BC=3a/2

введите сюда описание изображения

Будем спавнить шестиугольники следующим образом:

  • Идем по горизонтали, спавним шестигольуники со сдвигом sqrt(3)/2
  • Когда линия заканчивается переходим на линию вверх (на 3a/2)
  • Переходе между линиями первый слева шестиугольник будем спавнить то на a*sqrt(3)/2 влево, то на это же значение вправо.

У меня получился такой код, который спавнит шестиугольники по осям XZ, оставляя Y постоянным.

public Vector2Int FieldSize;
    public Vector3 InitPos; // Позиция левого нижнего тайла
    public float HexagonSide; // Сторона шестиугольника (`а` на чертеже)
    public GameObject Hexagon; // Префаб
    private void Start()
    {
        Vector2 Offset = new Vector2(Mathf.Sqrt(3) * HexagonSide,
                                    3 / 2f * HexagonSide); // Сдвиги по X и Y
        float LinesOffsetX = Mathf.Sqrt(3) / 2 * HexagonSide; // Сдвиг по X между линиями
        float currLineOffset = 0; // Сдвиг по X на НЫНЕШНЕЙ линии
        for (int i = 0; i < FieldSize.x; i++)
        {
            for (int j = 0; j < FieldSize.y; j++)
            {
            Vector3 pos = new Vector3(InitPos.x + Offset.x * j + currLineOffset, 
                                      InitPos.y, 
                                      InitPos.z + Offset.y * i);
            Instantiate(Hexagon, pos, ...); // Последующие параметры кастомны
        }
        currLineOffset = (currLineOffset == 0 ? LinesOffsetX : 0);
    }
}

Спавнить шестиугольники можно и по-другому, перпедикулярно от моего решения. В таком случае сдвиги будут немного другие.


Комментарий по поводу именно вашего кода:

  • Очевидно, что вы используете шестиугольники одинаковых размеров, так что получение этих самых размеров лучше вынести из двойного цикла (первая строка тела цикла).
  • Есть вариант хранения в переменной центра предыдущего шестиугольника. Каждую итерацию рассчитываем позицию нового. Но я не хочу это реализовывать, потому что уже есть рабочий вариант, поэтому просто оставлю это здесь – Максим Фисман Aug 21 '21 at 12:25