EDIT: working! I’ll reply with how I worked around the issue.
Here’s the problem: When items that get picked up off the ground are destroyed (upon being picked up), I can’t instantiate a new item on the ground if I drop it out of my inventory. I’ve tried a lot it seems… I have a variable in my Item class Item.Prefab.
I set the prefab to itself in the gameobject. I know that some of the code doesn’t instantiate or use this prefab… I couldn’t get it to work with or without it.
You can see that my health prefab refers to itself here: Screenshot - e71aa342d17ffef4493f30b18f32a475 - Gyazo
Really sorry this is a lot to look through. There’s one way I can make this implementation work: Make two prefabs of every single item I have in game, set the itemprefab of first prefab (that my spawnitemscript spawns) to the second/copy prefab and then just destroy the object that is on the ground.
How do I make this work with just one prefab per item and prevent it from failing when instantiating? It tells me I already destroyed the prefab:
(startslot is just an inventory slot that has the items we want to drop).
foreach (Item item in startSlot.Items)
{
GameObject temporaryDrop = (GameObject)GameObject.Instantiate(item.gameObject, playerRef.transform.position, Quaternion.identity);
temporaryDrop.GetComponent<Item>().SetItemStatsOnDrop(item);
}
Here’s all the code you should need to decipher and a rundown of it:
On the start of my scene, I instantiate all the items I want in my scene through this script. I just have prefabs in the slots:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SpawnAndTrackItems : MonoBehaviour
{
public Hashtable ItemsOnGround;
public List<GameObject> SceneItems;
void Start ()
{
ItemsOnGround = new Hashtable();
SpawnSceneItems();
}
private void SpawnSceneItems()
{
foreach (var item in SceneItems)
{
//GameObject prefab = item.GetComponent<Item>().prefab;
GameObject itemRef = (GameObject)Instantiate(item, item.transform.position, Quaternion.identity);
ItemsOnGround.Add(itemRef, item.transform.position);
}
}
}
Next, if a Player clicks an item on the ground, a variable (itemClicked) referencing the item script on the gameobject that was clicked is set and the following code runs:
if (itemClicked && agent.transform.position == itemClickedDestination)
{
foreach (var itemName in trackItemsScript.ItemsOnGround.Keys)
{
if (itemName.Equals(itemClicked.gameObject))
{
GameObject itemToAdd = (GameObject)itemName;
inventory.ClickToPickUpItem(itemClicked);
Destroy(itemToAdd);
}
}
//itemClicked.DestroySelf();
}
Upon looking around the forums for similar problems, I saw this and implemented it on my Item script so it will properly destroy the item?:
public void DestroySelf()
{
Destroy(gameObject);
Destroy(this);
}
So I pick up the item and add it to my slot
/**
* Everything eventually goes through "addItemPrfeab" when adding items to the slot.
* */
public bool ClickToPickUpItem(Item item)
{
if (item.maxStackSize == 1 && emptySlotCount == 0)
{
Debug.Log("Could not pick up " + item.itemName + ", inventory is too full.");
return false;
}
else if (item.maxStackSize == 1 && emptySlotCount > 0)
{
Debug.Log("Picked up " + item.itemName + ".");
PlaceEmpty(item);
return true;
}
else
{
foreach (GameObject slot in allInventorySlots)
{
Slot temp = slot.GetComponent<Slot>();
if (!temp.IsEmpty)
{
if (temp.currentItem.type == item.type && temp.canAdd)
{
//add the item prefab, this is filling an empty slot with a "brand new" item
temp.AddItemPrefab(item);
return true;
}
}
}
if (EmptySlotCount > 0)
{
Debug.Log("Picked up " + item.itemName + ".");
PlaceEmpty(item);
}
else
{
Debug.Log("Could not pick up " + item.itemName + ", inventory is too full.");
}
}
return false;
}
private bool PlaceEmpty(Item item)
{
if (EmptySlotCount > 0)
{
foreach (GameObject slot in allInventorySlots)
{
Slot temp = slot.GetComponent<Slot>();
if (temp.IsEmpty)
{
temp.AddItemPrefab(item);
temp.defaultClick = item.defaultClick;
temp.clickTypeOptions = item.clickTypeOptions;
EmptySlotCount--;
return true;
}
}
}
return false;
}
The item that I add to my inventory is the item that was stored in itemClicked.
public void AddItemPrefab(Item item)
{
Items.Push(item);
this.itemName = item.itemName;
if (Items.Count > 1)
{
stackText.text = Items.Count.ToString();
}
ChangeSprite(item.spriteNeutral, item.spriteHighlighted);
}