我已经完成了库存槽,并希望锁定和解锁一些槽,以便在...之后扩展(按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);
}
}
}
解锁插槽不增加(调试未显示),其余插槽无法使用
答案 0 :(得分:0)
已修复:只需将启动功能复制到fixedupdate。
不要!
这对于资源来说听起来很糟糕……为什么要一直设置呢?而是将其移至您实际更改unlockSlot
的那一刻,并仅一次进行。
此外,您还使用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);
}
}