[BUG] Dragging and dropping an item from the Equipped collection onto itself in the Main collection causes an exception

trueh

New member
Hello:

If I have an item equipped and I drag it back onto itself in the main collection, an exception is produced and the item gets deleted. I am using tthe latest version of Ultimate Inventory System on Unity 2021.3.18f1 (LTS) with the built-in rendering pipeline.

The steps to reproduce can be seen in this video: https://streamable.com/dd4x28

The exception produced is the following:

[Exception] NullReferenceException: Object reference not set to an instance of an object ItemSlotCollection.GetItemSlotIndex() at /Opsive/UltimateInventorySystem/Scripts/Core/InventoryCollections/ItemSlotCollection.cs:496 494: if (m_ItemsBySlot[i].Item == item) { return i; } -->496: if (m_ItemsBySlot[i].Item.StackableEquivalentTo(item)) { 497: stackableEquivalentItemIndex = i; 498: } ItemSlotCollection.RemoveItem() at /Opsive/UltimateInventorySystem/Scripts/Core/InventoryCollections/ItemSlotCollection.cs:432 430: public override ItemInfo RemoveItem(ItemInfo itemInfo) 431: { -->432: var itemSlot = GetItemSlotIndex(itemInfo.Item); 433: if (itemSlot == -1) { 434: return (0, itemInfo.Item, this); Inventory.RemoveItem() at /Opsive/UltimateInventorySystem/Scripts/Core/InventoryCollections/Inventory.cs:517 515: public virtual ItemInfo RemoveItem(ItemInfo itemInfo) 516: { -->517: if (ReferenceEquals(itemInfo.Inventory, this)) { return itemInfo.ItemCollection.RemoveItem(itemInfo); } 519: return MainItemCollection.RemoveItem(itemInfo); InventoryGrid.RemoveItem() at /Opsive/UltimateInventorySystem/Scripts/UI/Item/InventoryGrid.cs:149 147: public override ItemInfo RemoveItem(ItemInfo itemInfo, int index) 148: { -->149: return Inventory.RemoveItem(itemInfo); 150: } ItemViewDropContainerSmartExchangeAction.Drop() at /Opsive/UltimateInventorySystem/Scripts/UI/Item/DragAndDrop/DropActions/ItemViewDropContainerSmartExchangeAction.cs:154 153: if (destinationGiveSourceReceive) { -->154: itemViewDropHandler.StreamData.DestinationItemInfo = itemViewDropHandler.DestinationContainer.RemoveItem(itemViewDropHandler.StreamData.DestinationItemInfo, itemViewDropHandler.DestinationIndex); 155: } ItemViewDropActionsWithConditions.Drop() at /Opsive/UltimateInventorySystem/Scripts/UI/Item/DragAndDrop/ItemViewSlotDropActionSet.cs:235 233: public void Drop(ItemViewDropHandler itemViewDropHandler) 234: { -->235: for (int i = 0; i < m_Actions.Length; i++) { m_Actions[i].Drop(itemViewDropHandler); } 236: } 237: } ItemViewSlotDropActionSet.HandleItemViewSlotDrop() at /Opsive/UltimateInventorySystem/Scripts/UI/Item/DragAndDrop/ItemViewSlotDropActionSet.cs:116 114: if (index == -1) { return; } -->116: m_ActionsWithConditions[index].Drop(itemViewDropHandler); 117: } ItemViewDropHandler.HandleItemViewSlotDropInternal() at /Opsive/UltimateInventorySystem/Scripts/UI/Item/DragAndDrop/ItemViewDropHandler.cs:259 257: { 258: if (m_ItemViewSlotDropActionSet == null) { return; } -->259: m_ItemViewSlotDropActionSet.HandleItemViewSlotDrop(this); 261: if (SourceContainer != null) { ItemViewDropHandler.HandleItemViewSlotDrop() at /Opsive/UltimateInventorySystem/Scripts/UI/Item/DragAndDrop/ItemViewDropHandler.cs:249 248: m_ItemViewSlotCursorManager.BeforeDrop(); -->249: HandleItemViewSlotDropInternal(); 250: m_ItemViewSlotCursorManager.RemoveItemView(); 251: } ItemViewSlotsContainerBase+<>c__DisplayClass78_0.<Initialize>b__7() at /Opsive/UltimateInventorySystem/Scripts/UI/Item/ItemViewSlotsContainerBase.cs:275 273: m_ItemViewSlotDropEventData.SetValues(this, localIndex); 274: m_ItemViewSlotDropEventData.PointerEventData = pointerEventData; -->275: OnItemViewSlotDropE?.Invoke(m_ItemViewSlotDropEventData); 276: }; 277: } ActionButton.OnDrop() at /Opsive/UltimateInventorySystem/Scripts/UI/CompoundElements/ActionButton.cs:264 262: public virtual void OnDrop(PointerEventData eventData) 263: { -->264: OnDropE?.Invoke(eventData); 265: } ExecuteEvents.Execute() at Library/PackageCache/com.unity.ugui@1.0.0/Runtime/EventSystem/ExecuteEvents.cs:92 90: private static void Execute(IDropHandler handler, BaseEventData eventData) 91: { -->92: handler.OnDrop(ValidateEventData<PointerEventData>(eventData)); 93: } ExecuteEvents.Execute[T]() at Library/PackageCache/com.unity.ugui@1.0.0/Runtime/EventSystem/ExecuteEvents.cs:272 270: try 271: { -->272: functor(arg, eventData); 273: } 274: catch (Exception e) ExecuteEvents.ExecuteHierarchy() RewiredStandaloneInputModule.ProcessMousePress() at /Rewired/Integration/UnityUI/RewiredStandaloneInputModule.cs:1093 1091: ExecuteEvents.Execute(pointerEvent.pointerPress, pointerEvent, ExecuteEvents.pointerClickHandler); 1092: } else if (pointerEvent.pointerDrag != null && pointerEvent.dragging) { -->1093: ExecuteEvents.ExecuteHierarchy(currentOverGo, pointerEvent, ExecuteEvents.dropHandler); 1094: } RewiredStandaloneInputModule.ProcessMouseEvent() at /Rewired/Integration/UnityUI/RewiredStandaloneInputModule.cs:992 991: // Process the first mouse button fully -->992: ProcessMousePress(leftButtonData); 993: ProcessMove(leftButtonData.buttonData); 994: ProcessDrag(leftButtonData.buttonData); RewiredStandaloneInputModule.ProcessMouseEvents() at /Rewired/Integration/UnityUI/RewiredStandaloneInputModule.cs:976 974: int pointerCount = GetMouseInputSourceCount(playerIds[i]); 975: for(int j = 0; j < pointerCount; j++) { -->976: ProcessMouseEvent(playerIds[i], j); 977: } 978: } RewiredStandaloneInputModule.Process() at /Rewired/Integration/UnityUI/RewiredStandaloneInputModule.cs:690 688: // touch needs to take precedence because of the mouse emulation layer 689: if (!ProcessTouchEvents()) { -->690: if (isMouseSupported) ProcessMouseEvents(); 691: } 692: } EventSystem.Update() at Library/PackageCache/com.unity.ugui@1.0.0/Runtime/EventSystem/EventSystem.cs:501 500: if (!changedModule && m_CurrentInputModule != null) -->501: m_CurrentInputModule.Process(); 503: #if UNITY_EDITOR

Regards.
 
This one can be solved in ItemSlotCollection.cs changing from:

Code:
public int GetItemSlotIndex(Item item){

var stackableEquivalentItemIndex = -1;
for (int i = 0; i < m_ItemSlotSet.ItemSlots.Count; i++) {
var itemSlot = m_ItemSlotSet.ItemSlots[i];
if (itemSlot.Category != null && !itemSlot.Category.InherentlyContains(item)) {
continue;
}

if (m_ItemsBySlot[i] == null) { continue; }

if (m_ItemsBySlot[i].Item == item) { return i; }

if (m_ItemsBySlot[i].Item.StackableEquivalentTo(item)) {
stackableEquivalentItemIndex = i;
}
}

return stackableEquivalentItemIndex;
}

to:

Code:
public int GetItemSlotIndex(Item item){

var stackableEquivalentItemIndex = -1;
for (int i = 0; i < m_ItemSlotSet.ItemSlots.Count; i++) {
var itemSlot = m_ItemSlotSet.ItemSlots[i];
if (itemSlot.Category != null && !itemSlot.Category.InherentlyContains(item)) {
continue;
}

if (m_ItemsBySlot[i] == null) { continue; }

if (m_ItemsBySlot[i].Item == null) { continue; }

if (m_ItemsBySlot[i].Item == item) { return i; }

if (m_ItemsBySlot[i].Item.StackableEquivalentTo(item)) {
stackableEquivalentItemIndex = i;
}
}

return stackableEquivalentItemIndex;
}

I have just added
Code:
if (m_ItemsBySlot[i].Item == null) { continue; }


Regards.
 
Thank you for letting us know. There was a change that now allows null items in the ItemSlotCollection in the last update. I must have missed this exception.
I've added your change in the source code
 
Top