前言
欢迎来到【制作100个Unity游戏】系列!本系列将引导您一步步学习如何使用Unity开发各种类型的游戏。在这第25篇中,我们将探索如何用unity制作一个3D背包、库存、制作、快捷栏、存储系统、砍伐树木获取资源、随机战利品宝箱等功能,我会附带项目源码,以便你更好理解它。
制作系统
定义制作配方
// 制作配方 [CreateAssetMenu(fileName = "NewRecipe", menuName = "Inventory/Recipe")] public class Recipe : ScriptableObject { // 生成的物品预制体 public GameObject createdItemPrefab; // 生产数量 public int quantityProduced = 1; // 所需的原料列表 public List<RequiredIngredient> requiredIngredients = new List<RequiredIngredient>(); // 所需的原料 [System.Serializable] public class RequiredIngredient { // 原料的名称 public string itemName; // 所需的数量 public int requiredQuantity; } }
简单配置一个制作配方
新增Crafting,实现制作功能,注意修改Inventory为单例
using System.Collections.Generic; using UnityEngine; public class Crafting : MonoBehaviour { public List<Slot> allInventorySlots; [Header("制作")] public List<Recipe> itemRecipes = new List<Recipe>();//制作配方列表 private void Start() { allInventorySlots = Inventory.Instance.allInventorySlots; } //合成制作物品 public void craftItem(string itemName) { // 遍历所有配方 foreach (Recipe recipe in itemRecipes) { // 找到与指定物品名称匹配的配方 if (recipe.createdItemPrefab.GetComponent<Item>().name == itemName) { bool haveAllIngredients = true;//是否有足够的原料 for (int i = 0; i < recipe.requiredIngredients.Count; i++) { if (!haveIngredient(recipe.requiredIngredients[i].itemName, recipe.requiredIngredients[i].requiredQuantity)) { Debug.Log(recipe.requiredIngredients[i].itemName + "不够,制作失败"); haveAllIngredients = false; break; } } if (haveAllIngredients) { // 移除所需的原料 for (int i = 0; i < recipe.requiredIngredients.Count; i++) { removeIngredient(recipe.requiredIngredients[i].itemName, recipe.requiredIngredients[i].requiredQuantity); } // 创建物品 GameObject craftedItem = Instantiate(recipe.createdItemPrefab, Inventory.Instance.dropLocation.position, Quaternion.identity); craftedItem.GetComponent<Item>().currentQuantity = recipe.quantityProduced; // 将物品添加到库存中 Inventory.Instance.addItemToInventory(craftedItem.GetComponent<Item>()); break; } } } } //从库存中移除指定数量的原料 private void removeIngredient(string itemName, int quantity) { // 如果没有足够的原料,则直接返回 if (!haveIngredient(itemName, quantity)) { Debug.Log("没有足够的原料"); return; } int remainingQuantity = quantity; // 遍历所有库存槽位 foreach (Slot curSlot in allInventorySlots) { Item item = curSlot.getItem(); // 找到匹配的原料 if (item != null && item.name == itemName) { // 如果库存中的数量大于所需数量,则减去所需数量 if (item.currentQuantity >= remainingQuantity) { item.currentQuantity -= remainingQuantity; // 如果库存中的数量等于所需数量,则将槽位置空 if (item.currentQuantity == 0) { curSlot.setItem(null); } return; } else { Debug.Log("没有足够的原料"); // 更新剩余数量 // remainingQuantity -= item.currentQuantity; // curSlot.setItem(null); } } } } //检查库存中是否有足够的指定原料 private bool haveIngredient(string itemName, int quantity) { int foundQuantity = 0; // 遍历所有库存槽位 foreach (Slot curSlot in allInventorySlots) { // 如果槽位存在物品且名称匹配 if (curSlot.hasItem() && curSlot.getItem().name == itemName) { foundQuantity += curSlot.getItem().currentQuantity; // 如果找到的数量大于所需数量,则返回true,否则返回false if (foundQuantity >= quantity) { return true; } } } return false; } }
绑定配方参数
绘制简单的制作界面,并并绑定点击制作事件
效果,制作出一个石斧
源码
源码不出意外的话我会放在最后一节