我要开始限制项目插槽,然后按M键更新扩展插槽

时间:2019-09-06 06:11:31

标签: c# unity3d inventory

我已经完成了库存槽,并希望锁定和解锁一些槽,以便在...之后扩展(按m进行测试)

我按M并现在增加解锁槽,但是在增加解锁槽数量后无法使用扩展槽。

已完成所有库存位置和可在位置之间移动的物品

public abstract class ItemContainer : MonoBehaviour, IItemContainer
{
    public List<ItemSlot> ItemSlots;

    public int unlockSlot = 1;

    public event Action<BaseItemSlot> OnPointerEnterEvent;
    public event Action<BaseItemSlot> OnPointerExitEvent;
    public event Action<BaseItemSlot> OnRightClickEvent;
    public event Action<BaseItemSlot> OnBeginDragEvent;
    public event Action<BaseItemSlot> OnEndDragEvent;
    public event Action<BaseItemSlot> OnDragEvent;
    public event Action<BaseItemSlot> OnDropEvent;

    protected virtual void OnValidate()
    {
        GetComponentsInChildren(includeInactive: true, result: ItemSlots);
    }

    protected virtual void Start()
    {
        for (int i = 0; i < ItemSlots.Count/5* unlockSlot; i++)
        {
            ItemSlots[i].OnPointerEnterEvent += slot => EventHelper(slot, OnPointerEnterEvent);
            ItemSlots[i].OnPointerExitEvent += slot => EventHelper(slot, OnPointerExitEvent);
            ItemSlots[i].OnRightClickEvent += slot => EventHelper(slot, OnRightClickEvent);
            ItemSlots[i].OnBeginDragEvent += slot => EventHelper(slot, OnBeginDragEvent);
            ItemSlots[i].OnEndDragEvent += slot => EventHelper(slot, OnEndDragEvent);
            ItemSlots[i].OnDragEvent += slot => EventHelper(slot, OnDragEvent);
            ItemSlots[i].OnDropEvent += slot => EventHelper(slot, OnDropEvent);
        }
    }

    private void EventHelper(BaseItemSlot itemSlot, Action<BaseItemSlot> action)
    {
        if (action != null)
            action(itemSlot);
    }

    public virtual bool CanAddItem(Item item, int amount = 1)
    {
        int freeSpaces = 0;

        foreach (ItemSlot itemSlot in ItemSlots)
        {
            if (itemSlot.Item == null || itemSlot.Item.ID == item.ID)
            {
                freeSpaces += item.MaxStacks - itemSlot.Amount;
            }
        }
        return freeSpaces >= amount;
    }

    public virtual bool AddItem(Item item)
    {
        for (int i = 0; i < ItemSlots.Count; i++)
        {
            if (ItemSlots[i].CanAddStack(item))
            {
                ItemSlots[i].Item = item;             
                ItemSlots[i].Amount++;               
                return true;
            }
        }

        for (int i = 0; i < ItemSlots.Count; i++)
        {
            if (ItemSlots[i].Item == null)
            {
                if (item.ID == item.ID)
                {
                    ItemSlots[i].Item = item;
                    ItemSlots[i].Amount++;
                    return true;
                }

            }
        }
        return false;
    }

    public virtual bool RemoveItem(Item item)
    {
        for (int i = 0; i < ItemSlots.Count; i++)
        {
            if (ItemSlots[i].Item == item)
            {
                ItemSlots[i].Amount--;
                return true;
            }
        }
        return false;
    }

    public virtual Item RemoveItem(string itemID)
    {
        for (int i = 0; i < ItemSlots.Count; i++)
        {
            Item item = ItemSlots[i].Item;
            if (item != null && item.ID == itemID)
            {
                ItemSlots[i].Amount--;
                return item;
            }
        }
        return null;
    }

    public virtual int ItemCount(string itemID)
    {
        int number = 0;

        for (int i = 0; i < ItemSlots.Count; i++)
        {
            Item item = ItemSlots[i].Item;
            if (item != null && item.ID == itemID)
            {
                number += ItemSlots[i].Amount;
            }
        }
        return number;
    }


    private void Update()
    {
        if (Input.GetKeyUp(KeyCode.M))
        {
            unlockSlot++;
            Debug.Log(unlockSlot);
        }
    }
}    

解锁插槽不增加(调试未显示),其余插槽无法使用

1 个答案:

答案 0 :(得分:0)

  

已修复:只需将启动功能复制到fixedupdate。

不要!

  1. 这对于资源来说听起来很糟糕……为什么要一直设置呢?而是将其移至您实际更改unlockSlot的那一刻,并仅一次进行。

  2. 此外,您还使用lambda表达式执行+=。因此,事件将添加为其他增量事件,因此下一次回调执行两次..然后执行3次,等等。 而且由于它是lambda表达式,所以您也不能使用-=来删除回调。

为了使其自动化一点,我将使用property with backing field之类的

private int unlockSlot = 1;
public int UnlockSlot
{
    get
    {
        return unlockSlot;
    }
    // you can additionally make the setter private so only this class
    // can change the value while other classes have only read permissions
    /*private*/
    set
    {
        unlockSlot = value;

        UpdateItemSlots();
    }
}

那么您可以避免使用EventHelper ..可以简单地写为

private void UpdateItemSlots()
{
    for (var i = 0; i < ItemSlots.Count / 5 * unlockSlot; i++)
    {
        // Before adding callbacks remove them
        // this is valid even if they were not added before
        // but makes sure they are added only exactly once
        ItemSlots[i].OnPointerEnterEvent -= OnPointerEnterEvent;
        ItemSlots[i].OnPointerExitEvent -= OnPointerExitEvent;
        ItemSlots[i].OnRightClickEvent -= OnRightClickEvent;
        ItemSlots[i].OnBeginDragEvent -= OnBeginDragEvent;
        ItemSlots[i].OnEndDragEvent -= OnEndDragEvent;
        ItemSlots[i].OnDragEvent -= OnDragEvent;
        ItemSlots[i].OnDropEvent -= OnDropEvent;

        // add your callback events .. no need for this complex lambda construct
        ItemSlots[i].OnPointerEnterEvent += OnPointerEnterEvent;
        ItemSlots[i].OnPointerExitEvent += OnPointerExitEvent;
        ItemSlots[i].OnRightClickEvent += OnRightClickEvent;
        ItemSlots[i].OnBeginDragEvent += OnBeginDragEvent;
        ItemSlots[i].OnEndDragEvent += OnEndDragEvent;
        ItemSlots[i].OnDragEvent += OnDragEvent;
        ItemSlots[i].OnDropEvent += OnDropEvent;
    }
}

Afaik,您不需要null检查event Action,就可以肯定地声明它们,并且以一种它们永远不会为空的方式声明它们,例如

public event Action<BaseItemSlot> OnPointerEnterEvent = slot => {};

这将添加一个空的回调,该回调如前所述由于是lambda表达式而无法删除=>确保OnPointerEnterEvent永远不会是null

现在只需更改

protected virtual void Start()
{
    UpdateItemSlots();
}

并且请记住不要使用unlockSlot而是使用UnlockSlot来更改其值,这样属性也会自动更新广告位

private void Update()
{
    if (Input.GetKeyUp(KeyCode.M))
    {
        UnlockSlot++;
        // for reading in this case it doesn't matter
        // but for being consequent I would also use the property here
        Debug.Log(UnlockSlot);
    }
}