Стаки предметов в одной ячейке на Unity C#

Реализовал систему инвентаря с помощью SO, создал предметы тоже с SO, но нужно чтобы когда игрок их поднимал они либо: а) собирались в стак, если их меньше чем максимальное значение стака; б) Предмет помещался в следующую ячейку и тд. возникает следующая проблема

public class Item : ScriptableObject
{
    public string Name;
    public int stackSize = 0; // Текущее количество в стаке
    public int maxStackSize = 10; // Максимальное количество в стаке
    public bool CanStack() //проверка для наличия места для след. предмета
    {
        return stackSize < maxStackSize;
    }
    public bool NoItems() //проверка на отсут. предмета, 
    {
        return stackSize == 0;
    }
}

при "подбирании" предмета - stackSize++; при выкидывании соответсвенно StackSize--; и в случае если предметов больше чем MaxStackSize происходит следующее

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

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

Я понимаю что решение состоит в том, чтобы каким то образом сохранять каждый предмет по отдельности в опр ячейки, но я не понимаю как это сделать. кто сможет помогите, буду премного благодарен


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

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

Ну здесь элемент может содержать следующие свойства:

public class InventoryItem : ScriptableObject
{
    public string Name = "Item";
    public int StackSize = 1; // размер стека, по умолчанию 1 
}

public class InventorySlot : ScriptableObject
{
    public InventoryItem Item = "Item";
    public int Count = 1; // количество

    public bool TryAdd(InventoryItem item, int count, out int addedCount)
    {
        int addedCount = 0;
        if (Item.Name == item.Name)
        {
            addedCount = Math.Max(Item.StackSize - Count - count, 0);
            if (addedCount > 0)
            {
                Count += addedCount;
                return true;
            }
        }
        return false;
    }
}

Показываю только добавление элементов

public class Inventory : MonoBehavior
{
    private readonly List<InventorySlot> Slots = new List<InventorySlot>();
    private const int maxSlots = 32;

    public bool TryAdd(InventoryItem item, int count, out int addedToInventory)
    {
        // дозаполняем стеки, где есть место
        foreach (InventorySlot slot in Slots)
        {
            if (count == 0)
                break;
            if (slot.TryAdd(item, count, out int added))
            {
                addedToInventory += added;
            }
        }

        // добавляем стеков
        while (count > 0 && Slots.Count < maxSlots)
        {
            InventorySlot newSlot = ScriptableObject.CreateInstance<InventorySlot>();
            newSlot.Item = item;
            Slots.Add(newSlot);
            if (slot.TryAdd(item, count, out int added))
            {
                addedToInventory += added;
            }
        }

        return addedToInventory> 0;
    }
}

Пользоваться как-то так:

InventoryItem item = ScriptableObject.CreateInstance<InventoryItem>();
item.Name = "Palka";
item.StackSize = 10;

int count = 150;
if (inventory.TryAdd(palka, count, out int added)
{
    Debug.Log($"Добавлено в инвентарь '{item.Name}': {added}");
    if (added == count)
    {
        Debug.Log($"Все '{item.Name}' поместились в инвентарь");
    }
    else
    {
        Debug.Log($"Не все '{item.Name}' поместились в инвентарь, количество лишних: {count - added}");
    }
}
else
{
    Debug.Log($"Не удалось добавить ни одной '{item.Name}', нет места");
}

То есть добавляя 150 палок в инвентарь, вы должны получить 15 слотов по 10.

Я конечно не спец в Unity, и это возможно не крутое решение, и можно лучше написать, но я старался максимально просто.

→ Ссылка