前言
欢迎来到【制作100个Unity游戏】系列!本系列将引导您一步步学习如何使用Unity开发各种类型的游戏。在这第25篇中,我们将探索如何用unity制作一个3D背包、库存、制作、快捷栏、存储系统、砍伐树木获取资源、随机战利品宝箱等功能,我会附带项目源码,以便你更好理解它。
存储加载物品信息
新增SaveInventory,保存和加载物品数据
public class SaveInventory : Singleton<SaveInventory> { [Header("保存加载")] public List<GameObject> allItemPrefabs = new List<GameObject>(); //物品预制体列表 private string saveFileName = "inventorySave.json"; //开始加载数据 private void Start() { loadInventory(); } //退出保存数据 private void OnApplicationQuit() { saveInventory(); } // 保存物品数据 private void saveInventory() { List<Slot> allInventorySlots = Inventory.Instance.allInventorySlots; InventoryData data = new InventoryData(); foreach (Slot slot in allInventorySlots) // 遍历所有插槽 { Item item = slot.getItem(); // 获取插槽中的物品 if (item != null) { ItemData itemData = new ItemData(item.name, item.currentQuantity, allInventorySlots.IndexOf(slot)); // 创建物品数据 data.slotData.Add(itemData); // 添加至插槽数据列表 } } string jsonData = JsonUtility.ToJson(data); // 序列化为 JSON 格式 File.WriteAllText(saveFileName, jsonData); // 将数据写入文件 } // 加载物品数据 public void loadInventory() { List<Slot> allInventorySlots = Inventory.Instance.allInventorySlots; if (File.Exists(saveFileName)) { string jsonData = File.ReadAllText(saveFileName); // 从文件中读取数据 InventoryData data = JsonUtility.FromJson<InventoryData>(jsonData); // 反序列化为 InventoryData 对象 Inventory.Instance.clearInventory(); // 清空物品 foreach (ItemData itemData in data.slotData) // 遍历插槽数据列表 { GameObject itemPrefab = allItemPrefabs.Find(prefab => prefab.GetComponent<Item>().name == itemData.itemName); // 根据物品名称查找对应的预制体 if (itemPrefab != null) { GameObject createdItem = Instantiate(itemPrefab, Inventory.Instance.dropLocation.position, Quaternion.identity); // 在指定位置创建物品 Item item = createdItem.GetComponent<Item>(); item.currentQuantity = itemData.quantity; // 设置物品数量 Inventory.Instance.addItemToInventory(item, itemData.slotIndex); // 将物品添加到相应插槽中 } } } foreach (Slot slot in allInventorySlots) // 更新所有插槽的数据 { slot.updateData(); } } } [System.Serializable] public class ItemData { public string itemName; // 物品名称 public int quantity; // 数量 public int slotIndex; // 插槽索引 public ItemData(string itemName, int quantity, int slotIndex) { this.itemName = itemName; this.quantity = quantity; this.slotIndex = slotIndex; } } [System.Serializable] public class InventoryData { public List<ItemData> slotData = new List<ItemData>(); // 插槽数据列表 }
修改Inventory
//将物品添加到背包中 public void addItemToInventory(Item itemToAdd, int overrideIndex = -1) { //如果指定了覆盖索引,则将物品添加到指定的槽位中 if(overrideIndex != -1 && overrideIndex < allInventorySlots.Count){ allInventorySlots[overrideIndex].setItem(itemToAdd); itemToAdd.gameObject.SetActive(false); allInventorySlots[overrideIndex].updateData(); return; } //。。。 } // 清空物品 public void clearInventory() { foreach (Slot slot in allInventorySlots) { slot.setItem(null); } }
注意:记得修改Inventory的Start方法为Awake或者OnEnable,确保Inventory初始化在SaveInventory的Start之前执行,不然会出错,对unity生命周期函数还不了解的小伙伴可以看我这篇文章:【2023Unity游戏开发教程】零基础带你从小白到超神05——脚本组件和生命周期函数
挂载配置参数
效果
先进入拾取物品,放在随机位置,退出游戏
查看保存的文件信息,在项目目录下
再次进入游戏,查看之前的物品被成功加载了
源码
源码不出意外的话我会放在最后一节