我使用C#在Unity中创建了一个库存系统。我目前在我的库存中有一个简单的堆栈系统,如果一个项目大于堆栈,它会停止将其添加到当前库存槽。但是我想知道如何设置它以便在另一个插槽已满时将相同项目的实例添加到不同的插槽中?
这是我的代码,如果你们需要我分享课程让我知道,任何帮助将不胜感激。
/**
* Controller class used to handle the logic and functionality of the
inventory system
**/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class InventoryController : MonoBehaviour
{
Inventory inv;
ItemDatabase database;
public int maxSize = 3;
private void Awake()
{
database = GetComponent<ItemDatabase>();
inv = GetComponent<Inventory>();
inv.slotAmount = 25;
inv.background = GameObject.Find("SlotBackgroundPanel");
inv.slotPanel = inv.background.transform.Find("SlotPanel").gameObject;
for (int i = 0; i < inv.slotAmount; i++)
{
inv.items.Add(new InventoryModel());
inv.slots.Add(Instantiate(inv.inventorySlot));
inv.slots[i].GetComponent<ItemSlot>().id = i;
inv.slots[i].transform.SetParent(inv.slotPanel.transform);
}
}
public void AddItem(int id)
{
InventoryModel itemToAdd = database.FetchItemByID(id);
if (itemToAdd.Stackable && CheckItemInInventory(itemToAdd))
{
for (int i = 0; i < inv.items.Count; i++)
{
if (inv.items[i].ID == id)
{
ItemData data = inv.slots[i].transform.GetChild(0).GetComponent<ItemData>();
data.amount++;
data.transform.GetChild(0).GetComponent<Text>().text = data.amount.ToString();
break;
}
}
}
else
{
for (int i = 0; i < inv.items.Count; i++)
{
if (inv.items[i].ID == -1)
{
inv.items[i] = itemToAdd;
GameObject itemObj = Instantiate(inv.inventoryItem);
itemObj.GetComponent<ItemData>().inventoryModel = itemToAdd;
itemObj.GetComponent<ItemData>().amount = 1;
itemObj.GetComponent<ItemData>().slot = i;
itemObj.transform.SetParent(inv.slots[i].transform);
itemObj.transform.position = Vector2.zero;
itemObj.GetComponent<Image>().sprite = itemToAdd.Sprite;
itemObj.name = itemToAdd.Title;
break;
}
}
}
}
public void RemoveItem(int id)
{
InventoryModel itemToRemove = database.FetchItemByID(id);
if (itemToRemove.Stackable && CheckItemInInventory(itemToRemove))
{
for (int j = 0; j < inv.items.Count; j++)
{
if (inv.items[j].ID == id)
{
ItemData data = inv.slots[j].transform.GetChild(0).GetComponent<ItemData>();
data.amount--;
data.transform.GetChild(0).GetComponent<Text>().text = data.amount.ToString();
if (data.amount == 0)
{
Destroy(inv.slots[j].transform.GetChild(0).gameObject);
inv.items[j] = new InventoryModel();
break;
}
if (data.amount == 1)
{
inv.slots[j].transform.GetChild(0).transform.GetChild(0).GetComponent<Text>().text = "";
break;
}
break;
}
}
}
else
{
for (int i = 0; i < inv.items.Count; i++)
{
if (inv.items[i].Title == null && inv.items[i].ID == id)
{
Destroy(inv.slots[i].transform.GetChild(0).gameObject); inv.items[i] = new InventoryModel();
break;
}
}
}
}
public void FullItem(int id)
{
InventoryModel itemIsFull = database.FetchItemByID(id);
if (itemIsFull.Stackable && CheckItemInInventory(itemIsFull))
{
for (int y = 0; y < inv.items.Count; y++)
{
if (inv.items[y].ID == id)
{
ItemData data = inv.slots[y].transform.GetChild(0).GetComponent<ItemData>();
data.transform.GetChild(0).GetComponent<Text>().text = data.amount.ToString();
if (data.amount >= maxSize)
{
inv.slots[y].transform.GetChild(0).transform.GetChild(0).GetComponent<Text>().text = "3";
data.amount = 3;
Debug.Log(data.amount);
break;
}
}
}
}
}
public bool CheckItemInInventory(InventoryModel inventoryModel)
{
for (int i = 0; i < inv.items.Count; i++)
if (inv.items[i].Title == inventoryModel.Title)
return true;
return false;
}
}
用于视图的类
using System.Collections;
/**
* View class, used to handle the User Interface
**/
using System.Collections.Generic;
using UnityEngine.UI;
using UnityEngine;
public class Inventory : MonoBehaviour
{
public GameObject background;
public GameObject slotPanel;
InventoryController inventoryController;
public GameObject inventorySlot;
public GameObject inventoryItem;
public int slotAmount;
public enum type { diamond = 0, iron = 1, gold = 2, fuel = 3 };
public List<InventoryModel> items = new List<InventoryModel>();
public List<GameObject> slots = new List<GameObject>();
private void Start()
{
inventoryController = GetComponent<InventoryController>();
inventoryController.AddItem((int)type.diamond);
inventoryController.AddItem((int)type.diamond);
inventoryController.AddItem((int)type.diamond);
inventoryController.AddItem((int)type.diamond);
inventoryController.AddItem((int)type.gold);
inventoryController.AddItem((int)type.fuel);
inventoryController.FullItem((int)type.diamond);
}
}
用于模型的类
/**
* Model class used to handle and store variables
**/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class InventoryModel
{
public int ID { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public bool Stackable { get; set; }
public string Slug { get; set; }
public Sprite Sprite { get; set; }
public InventoryModel(int id, string title, string description,
bool stackable, string slug)
{
this.ID = id;
this.Title = title;
this.Description = description;
this.Stackable = stackable;
this.Slug = slug;
this.Sprite = Resources.Load<Sprite>("Sprites/Items/" + slug);
}
public InventoryModel()
{
this.ID = -1;
}
}
Json文件
[
{
"id" : 0,
"title" : "Diamond",
"value" : 5,
"stats":{
"defence": 9,
"power" : 8,
"weight" : 5
},
"description": "Mined Diamond is stronger than metal",
"stackable" : true,
"rarity" : 10,
"slug": "Diamond"
},
{
"id" : 1,
"title" : "Iron",
"value" : 2,
"stats":{
"defence" : 5,
"power" : 6,
"weight" : 7
},
"description" : "Mined Iron is stronger than bronze",
"stackable" : false,
"rarity" : 6,
"slug" : "Metal"
},
{
"id" : 2,
"title" : "Gold",
"value" : 2,
"stats":{
"defence" : 0,
"power" : 0,
"weight" : 0
},
"description" : "Gold is valuable",
"stackable" : false,
"rarity" : 10,
"slug" : "Gold"
},
{
"id" : 3,
"title" : "Fuel2",
"value" : 2,
"stats":{
"defence" : 0,
"power" : 0,
"weight" : 0
},
"description" : "Fuel is needed for ship engines",
"stackable" : true,
"rarity" : 2,
"slug" : "Fuel2"
}
]
答案 0 :(得分:1)
啊,我在制作库存系统时记得这个问题。我做了类似的Minecraft,基于插槽,拖放等等。任何人丢失了源代码哇 我真的非常无聊所以我决定复制你的代码并添加一个函数来检查项目的数量是否小于最大堆栈大小。看看:
InventoryModel itemToAdd = database.FetchItemByID(id);
// First check if the item is in the inventory
// This check can be discarded. See below...
// You might be able to use this check in some form of anti-cheat system, so I've left it there.
if (CheckItemInInventory(itemToAdd))
{
// Iterate through the inventory and check items against their ID/Name
for (int i = 0; i < inv.items.Count; i++)
{
// If the item in the slot has the same ID as the item we want to add...
if (inv.items[i].ID == id)
{
// Check if the item is actually stackable and the slot is not full
// I.E the stack size (amount) is less than the max stack size.
// You'll need to add a new variable to your InventoryModel class
// int maxStackSize
if (inv.items[i].amount < inv.items[i].maxStackSize && itemToAdd.Stackable)
{
ItemData data = inv.slots[i].transform.GetChild(0).GetComponent<ItemData>();
data.amount++;
data.transform.GetChild(0).GetComponent<Text>().text = data.amount.ToString();
break;
}
// If not, then we skip adding a new item because this slot is already occupied and it's stack size is full
}
else if (inv.items[i].id == -1)
{
// If we encounter an empty slot, add a new item.
inv.items[i] = itemToAdd;
GameObject itemObj = Instantiate(inv.inventoryItem);
itemObj.GetComponent<ItemData>().inventoryModel = itemToAdd;
itemObj.GetComponent<ItemData>().amount = 1;
itemObj.GetComponent<ItemData>().slot = i;
itemObj.transform.SetParent(inv.slots[i].transform);
itemObj.transform.position = Vector2.zero;
itemObj.GetComponent<Image>().sprite = itemToAdd.Sprite;
itemObj.name = itemToAdd.Title;
}
}
// If the code's execution reaches this point, then we are essentially skipping action on the slot.
// This means that we were not able to find an item that matched the ID OR the stack size was full...
// So we keep scanning the other slots next in line...
}
else
{
// do something if the player tried to add an item but it does not exist in their inventory
// or something doesn't quite add up... Good for anti-cheat systems.
}
如您所见,我对您的代码进行了一些调整和一些优化,包括删除一些冗余检查。你正在检查玩家的库存两次。一旦验证他们是否有该项目,然后再次将该项目添加到库存。你可以一举完成这两项操作 我还应该提一下,我在visual studio中编写了代码,因此它应该适用于复制粘贴。享受!