当我在我的场景中选择一个项目时,它调用方法AddItem(),并且此方法会将项目添加到List并从场景中销毁游戏对象,但是当我尝试在列表中访问游戏对象时出现错误
MissingReferenceException:“GameObject”类型的对象已被销毁,但您仍在尝试访问它。
public class Inventory : MonoBehaviour
{
public List<GameObject> itemsGOInInventory = new List<GameObject>();
public void AddItem(GameObject itemToBeAdded)
{
itemsGOInInventory.Add(itemToBeAdded);
Destroy(itemToBeAdded);
}
public void FindItem(string name)
{
foreach (GameObject item in itemsGOInInventory)
{
if (item.GetComponent<Item>().itemName == "pistol")
{
Instantiate(item.GetComponent<Item>().itemObject,
this.transform);
}
}
}
}
答案 0 :(得分:3)
一旦你摧毁了游戏对象,它就消失了。
你可以做的是保持对该对象的引用,然后将其存储在某个地方并使其不可见。它被称为对象池。
Unity有一个关于此的教程:https://unity3d.com/learn/tutorials/topics/scripting/object-pooling
您需要将游戏对象SetActive设置为false或使用其他方法使其不可见。 https://docs.unity3d.com/ScriptReference/GameObject.SetActive.html
您已经拥有了对象列表,因此使用SetActive(false)来代替Destroy();
itemToBeAdded.SetActive(false);
希望这有帮助。
答案 1 :(得分:0)
你说你一旦捡起它就会摧毁它。一旦被销毁,它就不存在,并且对GameObject的所有引用都为空。在你的情况下保持游戏对象列表是一个坏主意。相反,您应该有库存物品的模型类。
public class InventoryItem
{
string name;
string description;
string spritePath;
// other variables
}
您应该创建一个单独的类来表示场景中的InventoryItem。你可以在你的游戏对象上有这样的东西:
public class InventoryItemView : MonoBehaviour
{
public InventoryItem item;
// ...
}
现在将项目脚本放在场景中的“项目”上。每当您选择一个项目时,从游戏对象获取InventoryItem脚本并将其添加到Inventory中的InventoryItems列表中。然后破坏游戏对象。现在即使你的游戏对象被销毁,你也有了你的InventoryItem对象。
public class Inventory : MonoBehaviour
{
public List<InventoryItem> itemsGOInInventory = new List<InventoryItem>();
public void AddItem(GameObject itemToBeAdded)
{
itemsGOInInventory.Add(itemToBeAdded.GetComponent<InventoryItemView>().item);
Destroy(itemToBeAdded);
}
//...
}
您可能想要检查GameObject是否具有InventoryItemView脚本。
理想情况下,您的库存类不应该是MonoBehaviour,可序列化的类已经足够了,但这不是主题。