So I have been following a tutorial on making a “Fortnite” style inventory system and all has been going well until today I ran into some issues. For some reason the code doesn’t work when I run it but it does on the tutorial. Whenever you try and switch/organize the items in your inventory it doesn’t act how it should. It basically is supposed to move the sprite from one spot to another but it moves the sprite and keeps it on the cursor even after you let go of the mouse button and you get this error:
Please help!
Here is the tutorial I am following:
Here are the two scripts that I use:
Script 1 (This script is the one to move the items:
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class UIElementDragger : MonoBehaviour
{
public const string DRAGGABLE_TAG = "UIDraggable";
public const string STATIC_TAG = "UIStatic"; // it is imperative that ONLY the InvSlot GameObjects have this tag
private float[,] UIBoundaries = new float[,]
{
//left, right
{1353f, 1900f},
//bottom, top
{55f, 160f}
};
private bool dragging = false;
private Vector2 originalPosition;
private Transform objectToDrag;
private Image objectToDragImage;
List<RaycastResult> hitObjects = new List<RaycastResult>();
private BRS_InventoryManager _IM;
private GameObject[] UISlots; //UI InventorySlots
private int[] _slots = new int[2];
#region Monobehaviour API
void Start()
{
_IM = GameObject.Find("BRS_Mechanics").GetComponent<BRS_InventoryManager>();
UISlots = GameObject.FindGameObjectsWithTag(STATIC_TAG);
}
void Update()
{
if (Input.GetMouseButtonDown(0))
{
objectToDrag = GetDraggableTransformUnderMouse();
if (objectToDrag != null)
{
//BRS - Addition
// remember the slot number
_slots[0] = GetUISlotNumber(objectToDrag.position);
dragging = true;
objectToDrag.SetAsLastSibling();
originalPosition = objectToDrag.position;
objectToDragImage = objectToDrag.GetComponent<Image>();
objectToDragImage.raycastTarget = false;
}
}
if (dragging)
{
objectToDrag.position = Input.mousePosition;
//Debug.Log(objectToDrag.position);
}
if (Input.GetMouseButtonUp(0))
{
if (objectToDrag != null)
{
var objectToReplace = GetDraggableTransformUnderMouse();
if (BoundaryCheck(objectToDrag.position))
{
//BRS - Addition
//Debug.Log("OBJECT OUT OF RANGE");
Destroy(objectToDrag.gameObject);
_IM.RemoveFromInventory(_slots[0]); ClearUISlots();
//Debug.Log("INSTANTIATE A NEW PICKUP ITEM HERE");
objectToDrag = null;
dragging = false;
return;
}
//BRS - Addition
// We need the ability to drop an item on an empty slot
// it also must snap in place
if (objectToReplace != null)
{
_slots[1] = GetUISlotNumber(objectToReplace.position);
objectToDrag.position = objectToReplace.position;
objectToReplace.position = originalPosition;
}
else
{
objectToDrag.position = GetStaticTransformUnderMouse().position;
_slots[1] = GetUISlotNumber(objectToDrag.position);
}
_IM.UpdateInventory(_slots[0], _slots[1]); ClearUISlots();
objectToDragImage.raycastTarget = true;
objectToDrag = null;
}
dragging = false;
}
}
//BRS - Addition
// Reports if the object position exceeds the defined boundaries
private bool BoundaryCheck(Vector3 pos)
{
float x = pos.x;
float y = pos.y;
float z = pos.z; //probably will not use this
if ((x < UIBoundaries[0, 0] || x > UIBoundaries[0, 1]) || (y < UIBoundaries[1, 0] || y > UIBoundaries[1, 1]))
return true;
// implied 'else' because we fell-through
return false;
}
// This is a convenience method - reduces the repetitive code
private void ClearUISlots()
{
_slots[0] = _slots[1] = -1;
}
private int GetUISlotNumber(Vector3 forPosition)
{
foreach (GameObject UISlot in UISlots)
{
if (UISlot.transform.position.x == forPosition.x)
{
int lastChar = UISlot.name.Length - 1;
return System.Int32.Parse(UISlot.name[lastChar].ToString());
}
}
return -1;
}
private GameObject GetObjectUnderMouse()
{
var pointer = new PointerEventData(EventSystem.current);
pointer.position = Input.mousePosition;
EventSystem.current.RaycastAll(pointer, hitObjects);
if (hitObjects.Count <= 0) return null;
return hitObjects.First().gameObject;
}
private Transform GetDraggableTransformUnderMouse()
{
var clickedObject = GetObjectUnderMouse();
// get top level object hit
if (clickedObject != null && clickedObject.tag == DRAGGABLE_TAG)
{
return clickedObject.transform;
}
return null;
}
private Transform GetStaticTransformUnderMouse()
{
var clickedObject = GetObjectUnderMouse();
if (clickedObject != null && clickedObject.tag == STATIC_TAG)
{
return clickedObject.transform;
}
return null;
}
#endregion
}
This is the second script (used to manage the items, whether that be dropping the item, switching it around, or something else):
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Photon.Pun;
public class BRS_InventoryManager : MonoBehaviour
{
public int numSlots = 6;
public InventoryItem[] ItemInv;
public int nextFreeSlot;
public GameObject newIcon;
public GameObject InventoryUIArea;
private Transform[] SlotCenters;
private GameObject SlotFrame;
public FN_ItemManager inItemMgr;
public string inItemName;
public bool canStack = false;
public bool canAdd = false;
public bool isViewingInventory = true;
public GameObject InventoryOverlay;
public GameObject TPC;
private GameObject _BRS_Mechanics;
public GameObject weaponHolder;
public GameHandler gameHandler;
private PhotonView view;
GameObject newItemObject;
GameObject newItemObject1;
GameObject newItemObject2;
GameObject newItemObject3;
GameObject newItemObject4;
GameObject newItemObject5;
bool hasArmorEquipped = false;
//private BRS_UIManager _UIM;
// Use this for initialization
void Start()
{
view = GetComponent<PhotonView>();
if (!view.IsMine)
{
Destroy(gameObject);
}
InventoryOverlay.SetActive(false);
ItemInv = new InventoryItem[numSlots];
_BRS_Mechanics = GameObject.Find("BRS_Mechanics");
//_UIM = GameObject.Find ("BRS_UI").GetComponent<BRS_UIManager> ();
InventoryUIArea = GameObject.Find("InvUI");
SlotCenters = InventoryUIArea.GetComponentsInChildren<Transform>();
//foreach(Transform t in SlotCenters)
//{
//Debug.Log(t.position.y);
//}
//Get the Slot Frames
SlotFrame = GameObject.Find("SlotFrame");
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyUp(KeyCode.Tab))
{
isViewingInventory = InvScreenViewing(isViewingInventory);
}
//We ignore the 0 index because for some reason a list of its children includes itself
if (Input.GetKeyUp("1"))
{
SlotFrame.transform.position = SlotCenters[1].position;
UpdateIcon(1);
}
if (Input.GetKeyUp("2"))
{
SlotFrame.transform.position = SlotCenters[2].position;
UpdateIcon(2);
}
if (Input.GetKeyUp("3"))
{
SlotFrame.transform.position = SlotCenters[3].position;
UpdateIcon(3);
}
if (Input.GetKeyUp("4"))
{
SlotFrame.transform.position = SlotCenters[4].position;
UpdateIcon(4);
}
if (Input.GetKeyUp("5"))
{
SlotFrame.transform.position = SlotCenters[5].position;
UpdateIcon(5);
}
if (Input.GetKeyUp("6"))
{
SlotFrame.transform.position = SlotCenters[6].position;
UpdateIcon(6);
}
}
public void UpdateIcon(int Slot)
{
GameObject[] ListofTiles = GameObject.FindGameObjectsWithTag("UIDraggable");
foreach (GameObject go in ListofTiles)
{
//Set them all to unselcted first
var SelectedIcon = go.transform.GetChild(0);
var UnSelectedIcon = go.transform.GetChild(1);
SelectedIcon.gameObject.SetActive(false);
UnSelectedIcon.gameObject.SetActive(true);
//Then find the one that matches our x value and set it to selected
if (go.transform.position.x == SlotCenters[Slot].position.x)
{
SelectedIcon.gameObject.SetActive(true);
UnSelectedIcon.gameObject.SetActive(false);
}
}
}
public bool InvScreenViewing(bool viewState)
{
if (viewState == true)
{
//If we are going to show the inventory
//Show the overlay
InventoryOverlay.SetActive(true);
}
else
{
//If we are NOT going to show the inventory
//Hide the overlay
InventoryOverlay.SetActive(false);
}
return !viewState;
}
public InventoryItem AddToInventory(InventoryItem newItem)
{
canAdd = false;
//Get a look at what type of item we are adding
//inItemMgr = newItem.GetComponent<FN_ItemManager> ();
//Get the name of the item
inItemName = newItem.ItemName;
//Debug.Log (inItemName);
//Do we already have one of those items?
//TODO - Full Paid Asset coming soon!
//Is it stackable?
canStack = newItem.isStackable;
//If we don't already have one, and it is stackable...
if (canStack && newItem.ItemsType != InventoryItem.ItemsTypeEnum.Ammo)
{
//Debug.Log ("Increase the inventory for this item.");
return newItem;
}
else
{
//If we don't already have one, and its NOT stackable...
//Debug.Log("Attempt to add it to our inventory if we have room");
if (newItem.isUseable)
{
newItemObject = PhotonNetwork.Instantiate(newItem.useableObject.name, newItem.useableObject.transform.position, newItem.useableObject.transform.rotation);
newItemObject.transform.SetParent(weaponHolder.transform);
WeaponSwitching weaponSwitching = weaponHolder.GetComponent<WeaponSwitching>();
weaponSwitching.EnableWeapon();
}
}
//Do we have room?
//If we get back a -1 that means that we are full up!
if (newItem.ItemsType != InventoryItem.ItemsTypeEnum.Ammo)
{
if (newItem.ItemsType == InventoryItem.ItemsTypeEnum.Armor && hasArmorEquipped == false)
{
hasArmorEquipped = true;
switch (newItem.ItemRarity)
{
case InventoryItem.ItemRarityEnum.Common:
gameHandler.SetBodyArmor(Character.BodyArmor.Tier_1);
break;
case InventoryItem.ItemRarityEnum.Uncommon:
gameHandler.SetBodyArmor(Character.BodyArmor.Tier_2);
break;
case InventoryItem.ItemRarityEnum.Rare:
gameHandler.SetBodyArmor(Character.BodyArmor.Tier_3);
break;
case InventoryItem.ItemRarityEnum.Epic:
Debug.Log("Epic Rarity");
gameHandler.SetBodyArmor(Character.BodyArmor.Tier_4);
break;
}
}
if (NextFreeSlot() < 0)
{
//Debug.Log ("You are overincumbered!");
return null;
}
else
{
// Adds the item
var newSlotID = NextFreeSlot();
ItemInv[newSlotID] = newItem;
canAdd = true;
AddInventoryIcon(newItem, newSlotID);
}
//canAdd = false;
return newItem;
}
else
{
WeaponSwitching weaponSwitching = weaponHolder.GetComponent<WeaponSwitching>();
int amount = int.Parse(newItem.ItemAmmount);
// Adds ammo to the weapon switching script
switch (newItem.AmmoType)
{
case InventoryItem.AmmoTypeEnum.Light:
weaponSwitching.lightAmmo += amount;
break;
case InventoryItem.AmmoTypeEnum.Heavy:
weaponSwitching.heavyAmmo += amount;
break;
case InventoryItem.AmmoTypeEnum.Sniper:
weaponSwitching.sniperAmmo += amount;
break;
case InventoryItem.AmmoTypeEnum.Shotgun:
weaponSwitching.shotgunAmmo += amount;
break;
}
return newItem;
}
}
public void RemoveFromInventory(int SlotNum)
{
var dropItem = ItemInv[SlotNum].LootPickUp;
if (ItemInv[SlotNum].ItemsType == InventoryItem.ItemsTypeEnum.Armor)
{
hasArmorEquipped = false;
gameHandler.SetBodyArmor(Character.BodyArmor.None);
}
else if (ItemInv[SlotNum].ItemsType == InventoryItem.ItemsTypeEnum.Gun)
{
GameObject weapon = weaponHolder.transform.GetChild(SlotNum).gameObject;
Destroy(weapon);
}
ItemInv[SlotNum] = null;
Instantiate(dropItem, TPC.transform.position, new Quaternion(0, 0, 0, 0));
}
public void UpdateInventory(int SlotNum1, int SlotNum2)
{
var tempSlot = ItemInv[SlotNum2];
//weaponHolder.transform.GetChild(SlotNum2).SetSiblingIndex(SlotNum1);
ItemInv[SlotNum2] = ItemInv[SlotNum1];
//weaponHolder.transform.GetChild(SlotNum1).SetSiblingIndex(SlotNum2);
ItemInv[SlotNum1] = tempSlot;
}
public int NextFreeSlot()
{
nextFreeSlot = System.Array.IndexOf(ItemInv, null);
//Return the next free slot index
return nextFreeSlot;
}
public void AddInventoryIcon(InventoryItem item, int SlotNum)
{
newIcon = Instantiate(item.InvTile);
newIcon.transform.SetParent(InventoryUIArea.transform);
newIcon.transform.localScale = new Vector3(1, 1, 1);
var Magic = 40 + (SlotNum * 92);
newIcon.transform.localPosition = new Vector3((Magic), 40, 0);
}
}
I don’t know if I have something setup wrong in the inspector or my script or what.
Thanks your help is greatly appreaciated!