Эффективная смена текстуры блока в зависимости от наличия соседних блоков

У меня есть скрипт на блоках, который в зависимости от положения и расположения рядом стоящих блоков меняет текстуру на нужную, когда ломался или ставился блок рядом, чтобы было плавная картинка в целом. Также есть объект мир со скриптом игровой логики, в котором содержатся все блоки в мире. Вопрос в следующем: лучше оставить как есть, то есть каждый блок сам отслеживает положения рядом стоящих блоков, или лучше в игровой логике проходить циклом по каждому блоку и проверять это положение для каждого? как лучше будет со стороны быстродействия или работоспособности


Ответы (1 шт):

Автор решения: Yaroslav

Именование для 2д поле:

  • 'Блок' называют Tile (плитка) или Cell (ячейка)
  • 'Мир' называют TileGrid/TileMap/TileBoard.

У тайла должно быть событие изменения, на которое реагируют соседние блоки.

using System;
using System.Collections.Generic;

public class Tile : MonoBehaviour
{
    public enum TileSide { Right, Left, Top, Down }

    public event Action Changed; // событие

    private Tile _right, _left, _top, _down;

    public void DoSomething ()
    {
        // изменения
        Changed?.Invoke(); // вызов события изменения
    }

    public void AddNeighbour (Tile tile, TileSide side)
    {
        switch (side) {
            case TileSide.Right:
                _right = tile;
                _right.Changed += OnNeighbourChange; // подписка на событие соседа
                break;
            case TileSide.Left:
                _left = tile;
                _left.Changed += OnNeighbourChange; // подписка на событие соседа
                break;
            case TileSide.Top:
                _top = tile;
                _top.Changed += OnNeighbourChange; // подписка на событие соседа
                break;
            case TileSide.Down:
                _down = tile;
                _down.Changed += OnNeighbourChange; // подписка на событие соседа
                break;
        }
    }

    private void OnNeighbourChange () // у одного из соседей изменения
    {
        
    }
}

public class TileGrid : MonoBehaviour
{
    [SerializeField] private Vector2Int _gridSize = new Vector2Int(10, 10);
    [SerializeField] private Vector2 _tileSize = new Vector2(32, 32);
    [Space]
    [SerializeField] private Tile _tileTemplate;
    private Tile[,] _grid;

    private void Start ()
    {
        _grid = new Tile[_gridSize.x, _gridSize.y];
        for (int x = 0; x < _gridSize.x; x++)
            for (int y = 0; y < _gridSize.y; y++)
            {
                _grid[x, y] = Instantiate(_tileTemplate, transform);
                _grid[x, y].transform.localPosition = new Vector3(x*_tileSize.x, y*_tileSize.y, 0);
            }
        for (int x = 0; x < _gridSize.x-1; x++)
            for (int y = 0; y < _gridSize.y-1; y++)
            {
                SetHorizontalTilePire(_grid[x, y], _grid[x+1, y]);
                SetVerticalTilePire(_grid[x, y], _grid[x, y+1]);
            }
    }

    private void SetHorizontalTilePire (Tile left, Tile right)
    {
        left.SetNeighbour(right, Tile.TileSide.Right);
        right.SetNeighbour(left, Tile.TileSide.Left);
    }

    private void SetVerticalTilePire (Tile down, Tile top)
    {
        down.AddNeighbour(top, Tile.TileSide.Top);
        top.AddNeighbour(down, Tile.TileSide.Down);
    }
}
→ Ссылка