Как положить один предмет в несколько слотов инвентаря

Работаю в Unity. Необходимо реализовать сетку из слотов, с возможностью перетаскивать на них предметы. Соответсвенно, если предметы размером с один слот, то нужно положить его в этот один слот. Но, если предмет, например, будет занимать два слота, то нужно каким-то образом проверить свободны ли эти слоты и, если да, то расположить предмет на этих слотах так, чтобы предмет занимал как раз эти два слота:)

Вопрос: как это правильней всего реализовать, как проверять свободен ли слот (Raycast или же collider), и как правильно привязывать предмет к нескольким слотам, как находить тот самый Anchor Point к которому нужно привязать объект?


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

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

Что использовать? Raycast? Сollider? Почему сразу не квантово-термоядерный компьютер? Это обычный двумерный массив bool[x, y], где каждый предмет забивает или освобождает его элементы в соответствие с размером, а сами предметы хранятся в List<Item>.

public class Bag : MonoBehaviour {
    public static Bag Main;
    [SerializeField] private Vector2Int _size = new Vector2Int(10, 10);
    private List<Item> _items;
    private bool[,] _fill;

    private void Awake () {
        Main = this;
        _fill = new bool[_size.x, _size.y];
    }

    public void AddItem (Item item) {
        _items.Add(item);
        RecalculateFill();
    }

    public void RemoveItem (Item item) {
        if (_items.Remove(item))
            RecalculateFill();
    }

    // Проверка на на возможность кинуть в сумку
    public bool CanDrop (Vector2Int tile, Vector2Int size) { 
        if (tile.x < 0 || tile.x+size.x > _size.x)
            return false;
        if (tile.y < 0 || tile.y+size.y > _size.y)
            return false;
        for (int x = 0; x < size.x; x++)
            for (int y = 0; y < size.y; y++)
                if (_fill[tile.x+x, tile.y+y])
                    return false;
        return true;
    }

    private void RecalculateFill () {
        for (int x = 0; x < _size.x; x++)
            for (int y = 0; y < _size.y; y++)
                _fill[x, y] = false;
        foreach (Item item in _items)
            for (int x = 0; x < item.Size.x; x++)
                for (int y = 0; y < item.Size.y; y++)
                    _fill[item.BagPosition.x+x, item.BagPosition.y+y] = true;
    }
}

public class Item : MonoBehaviour {
    [SerializeField] private Vector2Int _size = new Vector2Int(1, 2);
    private Vector2Int _bagPosition;

    public Vector2Int Size { get { return _size; } }
    public Vector2Int BagPosition { get { return _bagPosition; } }

    private void  Drag () {
        Bag Bag = Bag.Main;
        if (Bag != null) {
            if (Bag.CanDrop(_bagPosition, _size))
                Bag.AddItem(this);
        }
    }
}

В принципе можно и UI попробовать

Это UI! Иначе глупость.

→ Ссылка