Hi !
I'm working on an inventory system with large items (Diablo/Men of War/Commandos/"insertnameofagamehere"-style) for an RPG, but I can't find a proper way to move an item from one group of slot to another.
At first I was seeking for a way to get the UI elements that were under another UI element (dragging the item, get the hovered slots, check if they are occupied, red highlight them if they are, green highlight if they aren't, etc), but I didn't find a way to do that.
Of course, I tried to use the Event Handlers interfaces (and using the PointerEventData too). Sadly it doesn't behave exactly like I wanted because, for instance, PointerEventData.hovered returns all the UI elements under the Pointer, not the ones under the InventoryItem that I am dragging.
Raycasts could do it but I think it is a bit "overkill" to use raycasts between UI elements just for that, I'm sure there is a more performance-friendly way to do it.
I also tried colliders but the OnCollider/TriggerEnter/Exit don't seem to work on UI, or maybe I got it wrong.
I roamed Unity Answers and Youtube to find a way to do it but ain't find what I was looking for. If you got an idea or a tutorial that I missed that could do, please share it with me. I hope the post is clear enough so any can understand the problem here. Thank you by advance.
Here are the concerned scripts at the moment so everyone can understand where I am standing at the moment :
InventoryItem.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
public class InventoryItem : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler, IBeginDragHandler, IDragHandler, IEndDragHandler
{
[SerializeField] Image image;
[SerializeField] Animator animator;
Item item;
List containingSlots = new List();
List hoveredSlots = new List();
Inventory containingInventory;
public void Initialize(Item newItem, List newContainingSlots, Inventory newContainingInventory)
{
item = newItem;
containingSlots = newContainingSlots;
containingInventory = newContainingInventory;
name = item.name;
GetComponent().sizeDelta = new Vector2(50 * item.width, 50 * item.height);
GetComponent().anchoredPosition = containingSlots[0].GetComponent().anchoredPosition;
image.sprite = item.icon;
}
void IPointerEnterHandler.OnPointerEnter (PointerEventData eventData)
{
animator.SetBool("Highlighted", true);
}
public void OnPointerExit (PointerEventData eventData)
{
animator.SetBool("Highlighted", false);
}
public void OnBeginDrag(PointerEventData eventData)
{
// This allows to set the contaning slots to be set to innocuppied when starting to drag the item
containingInventory.RemoveItemAtSlot(containingSlots[0].slot);
}
public void OnDrag(PointerEventData eventdata)
{
// Some elegant logic to make the InventoryItem follow the pointer smoothly
transform.position = new Vector2(transform.position.x + eventdata.delta.x, transform.position.y + eventdata.delta.y);
// Some logic to get the slots that are hovered by the InventoryItem, which is our issue here that would look like this
/*
hoveredSlots.Clear();
for(int i = 0; i < SomeEventData.hovered.Count; i++)
{
if(SomeEventData.hovered[i].GetComponent() != null)
hoveredSlots.Add(SomeEventData.hovered[i].GetComponent();
}
*/
}
public void OnEndDrag(PointerEventData eventData)
{
CheckForRoom();
containingInventory.AddItemAtSlot(item, containingSlots[0]);
}
void CheckForRoom()
{
if(hoveredSlots[0].slot.containedItem == null)
{
for(int i = 0; i < hoveredSlots.Count; i++)
{
if(hoveredSlots[0].slot.occupied)
return;
}
}
containingSlots = hoveredSlots;
}
}
↧