Что это: Модуль проектировался как базовая инфраструктура для головоломок, тактических игр и настольных механик.
Как использовать: см. разделы ниже.
GridSystem — универсальный модуль сетки для Unity, который закрывает типовые задачи:
- генерация поля 2D/3D;
- настройка формы уровня (прямоугольник, hex-подобная форма, custom-маска);
- управление состояниями клетки (
enabled,walkable,occupied,content); - поиск пути с диагностикой причин, почему путь не найден;
- быстрый no-code workflow через Inspector;
- готовые прикладные слои для
Match3иTicTacToe.
Модуль проектировался как базовая инфраструктура для головоломок, тактических игр и настольных механик.
FieldGenerator— центральный runtime-компонент:- генерирует клетки;
- дает API доступа к ячейкам/соседям;
- хранит текущее состояние поля;
- предоставляет фасад pathfinding API.
FieldGeneratorConfig— конфигурация поля:- размер;
- правило перемещения;
- базовый тип формы (
GridType); - shape-mask и ручные override;
- origin-позиционирование поля относительно объекта (
Origin2D,OriginDepth,OriginOffset).
FieldCell— модель клетки:Position,Type,IsWalkable,IsEnabled,IsOccupied,ContentId,Flags.
GridShapeMask— ScriptableObject-маска формы.GridPathfinder— отдельный сервис pathfinding сGridPathRequest/GridPathResult.MovementRule— наборы направлений соседей (4/8/6/18/26, hex-like).FieldSpawner/FieldObjectSpawner— размещение префабов на сетке.FieldDebugDrawer— визуализация сетки и статусов клеток через Gizmos.
Neo.GridSystem.Match3Match3BoardServiceMatch3MatchFinderMatch3TileState
Neo.GridSystem.TicTacToeTicTacToeBoardServiceTicTacToeWinCheckerTicTacToeCellState
Каждая клетка (FieldCell) поддерживает несколько независимых измерений состояния:
IsEnabled— входит ли клетка в форму текущего уровня.IsWalkable— можно ли проходить через клетку при pathfinding.IsOccupied— занята ли клетка объектом.ContentId— произвольное игровое состояние (тип фишки Match3, X/O в TicTacToe и т.д.).Type— дополнительный пользовательский тип клетки.
Это разделение позволяет:
- отключать клетки геометрически, не ломая данные;
- держать разные правила проходимости для разных механик;
- использовать один и тот же грид в нескольких игровых режимах.
Поддерживается каскад формирования финального IsEnabled:
- Базовая форма (
GridType):RectangularHexagonal(аппроксимация через axial distance)Custom(база выключена, включение только через маску/override)
GridShapeMask:EnabledCells— whitelist;DisabledCells— blacklist.
- Ручные override в
FieldGeneratorConfig:DisabledCellsForcedEnabledCells
Дополнительно для проходимости:
BlockedCellsForcedWalkableCells
Это удобно для уровней Match3 с «дырками», асимметричными контурами и особыми тайлами.
FieldGenerator теперь поддерживает якорное размещение поля относительно Transform объекта.
Параметры:
Origin2D:- нижний ряд (
Bottom*), - центр (
*Center*), - верхний ряд (
Top*);
- нижний ряд (
OriginDepth:Front,Center,Back;OriginOffset: дополнительный ручной сдвиг в координатах клетки.
Практика:
- Для UI/пазлов чаще всего удобно
Origin2D = Center(по умолчанию), чтобы поле появлялось по центру объекта. - Для «роста от угла» выбирайте
BottomLeftили другой крайний якорь.
GridPathfinder работает через GridPathRequest и возвращает GridPathResult.
В запросе можно:
- передать
Directionsoverride (например, временно перейти с 4-way на 8-way); - игнорировать отдельные состояния (
IgnoreOccupied,IgnoreDisabled,IgnoreWalkability); - подключить
CustomPassabilityPredicate.
Результат дает:
Path(список клеток от старта до цели);Reason(NoPathReason) при неудаче.
NoPathReason:
InvalidStartOrEndStartNotPassableEndNotPassableNoPathFound
Это удобно для UI/дебага: можно показывать игроку не только «пути нет», но и почему.
Match3BoardService:
InitializeBoard()— заполнить поле случайными тайлами.TrySwapAndResolve(a, b)— обмен соседних клеток с валидацией и каскадным resolve.FindMatches()— получить текущие матч-группы.
Логика учитывает:
- только
IsEnabledклетки; - недоступные и занятые клетки не используются как валидные позиции.
Для рабочей demo-сцены Match3 используется runtime-представление поля:
GridSystemMatch3BoardView(Neo.Demo.GridSystem)- рисует фишки в world-space;
- поддерживает выбор клеток мышью;
- делает swap пары соседних клеток через
Match3BoardService.TrySwapAndResolve(...); - обновляет визуал при изменениях борда.
TicTacToeBoardService:
ResetBoard()TryMakeMove(Vector2Int/Vector3Int)IsBoardFull()
События:
OnPlayerChangedOnWinnerDetectedOnDrawDetectedOnBoardReset
Проверка победы вынесена в TicTacToeWinChecker.GetWinner(...).
Для рабочей demo-сцены TicTacToe используется runtime-представление поля:
GridSystemTicTacToeBoardView(Neo.Demo.GridSystem)- рисует кликабельные клетки в world-space;
- показывает
X/OпоContentId; - отправляет клик в
TicTacToeBoardService.TryMakeMove(...); - автоматически обновляется при reset/ходе/победе.
Это demo-компонент. Он не обязателен для core API, но нужен для визуальной и интерактивной сцены без дополнительной ручной сборки UI-поля.
FieldSpawner— простой спавнер на проходимых клетках.FieldObjectSpawner— спавн + трекинг по клеткам + управление занятостью.
Если occupiesSpace = true, FieldObjectSpawner синхронизирует FieldCell.IsOccupied.
Это напрямую влияет на pathfinding при PassabilityMode = WalkableEnabledAndUnoccupied.
FieldDebugDrawer рисует:
- сетку;
- клетки по цветам состояния:
- walkable
- blocked
- disabled
- occupied
- координаты;
- debug-path.
Для работы включите DebugEnabled у FieldGenerator.
- Создайте
GameObject, добавьте:Grid(Unity),FieldGenerator.
- Настройте
FieldGenerator.Config:Size,MovementRule,GridType,Origin2D(обычноCenter),OriginDepth(обычноCenter).
- Сгенерируйте поле:
- auto в
Awake/OnValidate, либоGenerateField().
- auto в
- По желанию добавьте:
FieldDebugDrawer,FieldSpawner/FieldObjectSpawner,Match3BoardServiceилиTicTacToeBoardService.
Для удобной ручной работы в Inspector у FieldGenerator доступны кнопки:
Regenerate FieldApply Shape && OverridesClear Manual OverridesSet Origin Center
var result = fieldGenerator.FindPathDetailed(
start: new Vector3Int(0, 0, 0),
end: new Vector3Int(7, 7, 0),
ignoreOccupied: false
);
if (result.HasPath)
{
Debug.Log($"Path length: {result.Path.Count}");
}
else
{
Debug.LogWarning($"No path: {result.Reason}");
}fieldGenerator.SetEnabled(new Vector3Int(2, 3, 0), false);
fieldGenerator.SetWalkable(new Vector3Int(1, 1, 0), false);
fieldGenerator.SetOccupied(new Vector3Int(4, 5, 0), true);
fieldGenerator.SetContentId(new Vector3Int(0, 0, 0), 2);bool success = match3Board.TrySwapAndResolve(
new Vector3Int(1, 2, 0),
new Vector3Int(2, 2, 0)
);bool moveApplied = tttBoard.TryMakeMove(new Vector2Int(1, 1));Сцены:
Assets/Neoxider/~Samples/Demo/Scenes/GridSystem/GridSystemMatch3Demo.unityAssets/Neoxider/~Samples/Demo/Scenes/GridSystem/GridSystemTicTacToeDemo.unity
Setup-скрипты:
Assets/Neoxider/~Samples/Demo/Scripts/GridSystem/GridSystemMatch3DemoSetup.csAssets/Neoxider/~Samples/Demo/Scripts/GridSystem/GridSystemTicTacToeDemoSetup.csAssets/Neoxider/~Samples/Demo/Scripts/GridSystem/GridSystemMatch3BoardView.cs(runtime view для интерактивного Match3 поля)Assets/Neoxider/~Samples/Demo/Scripts/GridSystem/GridSystemTicTacToeBoardView.cs(runtime view для кликабельного поля)
Если сцена пустая:
- Создайте объект.
- Добавьте соответствующий
*DemoSetup. - Нажмите
Setup Sceneв Inspector.
- Для новых игровых режимов используйте
ContentIdкак базовый state-id и держите собственный сервис-слой логики. - Не смешивайте «форму» (
IsEnabled) и «проходимость» (IsWalkable) — это разные уровни правил. - Для сложных уровней (Match3) используйте
GridType.Custom+GridShapeMask. - Для больших полей обновляйте только измененные клетки, а не полную регенерацию поля.