Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Positioning bug in an inventory system

Discussion in '2D' started by Mislav, Jun 6, 2016.

  1. Mislav

    Mislav

    Joined:
    Apr 1, 2016
    Posts:
    3
    Hello everyone,

    I have a bug with my inventory system. I have a script (which I'll include at the end of this post) which places a grid of Slots (which are set to children of SlotPanel) in my SlotPanel GameObject and then it adds Item GameObjects, which are children of the Slot they belong to.

    I have changed my computers during development time (I developed this on a PC and now I'm using my laptop). The problem arises when I resize my InventoryPanel (a parent to the SlotPanel, located in my Canvas), my Items don't display properly (in their Slots), but rather in the middle of their borders or even outside of InventoryPanel.

    Although I haven't resized the Inventory on my PC, I think the problem is with switching development computers. Someone suggested using canvas scaler or anchors (or both) to fix this problem. I also have to fix it because I'm implementing a drag&drop feature in my inventory system and this positioning problem is getting in the way.

    Here's my Inventory.cs code, where Slots and Items get instantiated:
    Code (CSharp):
    1.  using UnityEngine;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine.UI;
    5.  
    6. public class Inventory : MonoBehaviour
    7. {
    8.  
    9.   GameObject inventoryPanel;
    10.   GameObject slotPanel;
    11.   ItemDatabase database;
    12.   public GameObject inventorySlot;
    13.   public GameObject inventoryItem;
    14.  
    15.   int slotAmount;
    16.   public List<Item> items = new List<Item>();
    17.   public List<GameObject> slots = new List<GameObject>();
    18.    //private ItemDatabase itemDatabase;
    19.  
    20.    // Use this for initialization
    21.    void Start ()
    22.    {
    23.   database = GameObject.Find("ItemDatabase").GetComponent<ItemDatabase>();
    24.   slotAmount = 32;
    25.   inventoryPanel = GameObject.Find("InventoryPanel");
    26.   slotPanel = inventoryPanel.transform.FindChild("SlotPanel").gameObject;
    27.   for (int i = 0; i < slotAmount; i++)
    28.   {
    29.   items.Add(new Item());
    30.   GameObject slot = Instantiate(inventorySlot);
    31.   slot.transform.SetParent(slotPanel.transform);
    32.   slot.transform.localPosition = new Vector2(slotPanel.transform.localPosition.x, slotPanel.transform.localPosition.y);
    33.   slot.transform.localScale = new Vector2(1, 1);
    34.   slots.Add(slot);
    35.   }
    36.   AddItem(7);
    37.   for (int i = 0; i < 10; i++)
    38.   {
    39.   AddItem(8);
    40.   }
    41.   AddItem(1);
    42.      //itemDatabase = GameObject.FindGameObjectWithTag("ItemDatabase").GetComponent<ItemDatabase>();
    43.    }
    44.  
    45.   public void AddItem(int id)
    46.   {
    47.   Item itemToAdd = database.FetchItemByID(id);
    48.   if ((itemToAdd.itemType == Item.ItemType.Stackable) && (CheckIfItemIsInInventory(itemToAdd)))
    49.   {
    50.   for (int i = 0; i < items.Count; i++)
    51.   {
    52.   if (items[i].itemID == id)
    53.   {
    54.   ItemData data = slots[i].transform.GetChild(0).GetComponent<ItemData>();
    55.   if (data.amount < itemToAdd.itemStackLimit)
    56.   {
    57.   data.amount = data.amount + 1;
    58.   }
    59.   data.transform.GetChild(0).GetComponent<Text>().text = (data.amount).ToString();
    60.   break;
    61.   }
    62.   }
    63.   }
    64.   else
    65.   {
    66.   for (int i = 0; i < items.Count; i++)
    67.   {
    68.   if (items[i].itemID == -1)
    69.   {
    70.   items[i] = itemToAdd;
    71.   Sprite itemSprite = itemToAdd.itemIcon; // NullReferenceException here - not anymore
    72.   GameObject itemObjectInstance = Instantiate(inventoryItem);
    73.            itemObjectInstance.GetComponent<ItemData>().item = itemToAdd;
    74.   //itemObject.GetComponent<SpriteRenderer>().sprite = itemSprite;
    75.   //itemObject.GetComponent<SpriteRenderer>().sortingOrder = 1;
    76.   //GameObject itemObjectInstance = Instantiate(itemObject);
    77.   itemObjectInstance.transform.SetParent(slots[i].transform);
    78.   itemObjectInstance.transform.localPosition = new Vector2(slots[i].transform.localPosition.x, slots[i].transform.localPosition.y);
    79.   itemObjectInstance.transform.localScale = new Vector2(1, 1);
    80.   //itemObjectInstance.GetComponent<SpriteRenderer>().sprite = itemSprite;
    81.   // itemObjectInstance.GetComponent<SpriteRenderer>().sortingOrder = 0;
    82.   itemObjectInstance.GetComponent<Image>().sprite = itemSprite;
    83.   itemObjectInstance.name = itemToAdd.itemName;
    84.   //itemObjectInstance.transform.position = slots[i].transform.position;
    85.   break;
    86.   }
    87.   }
    88.   }
    89.   }
    90.  
    91.   bool CheckIfItemIsInInventory(Item item)
    92.   {
    93.   for (int i = 0; i < items.Count; i++)
    94.   {
    95.   if(items[i].itemID == item.itemID)
    96.   {
    97.   return true;
    98.   }
    99.   }
    100.   return false;
    101.   }
    102. }
    103.  
    Do you agree with using the canvas scaler and/or anchors or do you have other ideas? Is my script maybe faulty?

    Thanks in advance!

    EDIT: I played around with the Canvas Scaler and Anchors and I successfuly prevented Item icons from falling out of their slots, but I've got a problem with my drag&drop - I can take the item from a slot and drag it, but when I drop it it changes its position and dissapears into the unknown.

    Here's my script where I handle the drag&drop events:

    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4. using UnityEngine.EventSystems;
    5. using System;
    6.  
    7. public class ItemData : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler, IPointerDownHandler
    8. {
    9.   public Item item;
    10.   public int amount;
    11.  
    12.    private Transform _originalParent;
    13.    private Vector2 _offset;
    14.  
    15.    public void OnBeginDrag(PointerEventData eventData)
    16.    {
    17.      if (item != null)
    18.      {
    19.        // _offset = eventData.position - new Vector2 (this.transform.position.x, this.transform.position.y);
    20.        _originalParent = this.transform.parent;
    21.        this.transform.SetParent(this.transform.parent.parent);
    22.        this.transform.position = eventData.position - _offset;
    23.  
    24.      }
    25.    }
    26.  
    27.    public void OnDrag(PointerEventData eventData)
    28.    {
    29.      if (item != null)
    30.      {
    31.        this.transform.position = eventData.position - _offset;
    32.  
    33.      }
    34.    }
    35.  
    36.    public void OnEndDrag(PointerEventData eventData)
    37.    {
    38.      this.transform.SetParent(_originalParent);
    39.    }
    40.  
    41.    public void OnPointerDown(PointerEventData eventData)
    42.    {
    43.      if (item != null)
    44.      {
    45.        _offset = eventData.position - new Vector2(this.transform.position.x, this.transform.position.y);
    46.      }
    47.    }
    48. }
    49.  
    Any help here? Thanks!
     
    Last edited: Jun 6, 2016
  2. Mislav

    Mislav

    Joined:
    Apr 1, 2016
    Posts:
    3
    Fixed the bug. The problem was that whenever I moved dragged an item with my mouse and dropped it, my scale would be set to 0,0,0. So here's the fixed code:

    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4. using UnityEngine.EventSystems;
    5. using System;
    6.  
    7. public class ItemData : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler, IPointerDownHandler
    8. {
    9.   public Item item;
    10.   public int amount;
    11.  
    12.    private Transform _originalParent;
    13.    private Vector2 _offset;
    14.  
    15.    public void OnBeginDrag(PointerEventData eventData)
    16.    {
    17.      if (item != null)
    18.      {
    19.        // _offset = eventData.position - new Vector2 (this.transform.position.x, this.transform.position.y);
    20.        _originalParent = this.transform.parent;
    21.        this.transform.SetParent(this.transform.parent.parent);
    22.        this.transform.position = eventData.position - _offset;
    23.  
    24.      }
    25.    }
    26.  
    27.    public void OnDrag(PointerEventData eventData)
    28.    {
    29.      if (item != null)
    30.      {
    31.        this.transform.position = eventData.position - _offset;
    32.  
    33.      }
    34.    }
    35.  
    36.    public void OnEndDrag(PointerEventData eventData)
    37.    {
    38.      this.transform.SetParent(_originalParent);
    39.      this.transform.localScale = new Vector2 (1, 1); // solved the dissapearance problem (just a note: I've got a 2D game, you may want to change the Z position (use Vector3) if you've got a 3D game)
    40.    }
    41.  
    42.    public void OnPointerDown(PointerEventData eventData)
    43.    {
    44.      if (item != null)
    45.      {
    46.        _offset = eventData.position - new Vector2(this.transform.position.x, this.transform.position.y);
    47.      }
    48.    }
    49. }
    50.  
    Hope this helps!
     
    LiterallyJeff likes this.
  3. egartnuc

    egartnuc

    Joined:
    Jun 2, 2018
    Posts:
    23
    Im working on an inventory system as well and found this thread just from googling pointereventdata. I learnt alot from your code, though. Thank you.