前言
欢迎来到【制作100个Unity游戏】系列!本系列将引导您一步步学习如何使用Unity开发各种类型的游戏。在这第23篇中,我们将探索如何制作一个类似于七日杀和森林的生存游戏。
本篇内容会比较多,我会分几篇来实现,感兴趣的可以关注一下,以免错过内容更新。
本节主要实现了一个制作系统,并完成一个制作出石斧的功能。
源码
源码不出意外的话我会放在最后一节
制作系统
简单绘制制作系统面板UI
斧头素材
https://sketchfab.com/3d-models/stone-axe-3b634530c2f54128a150f723b6822d7b
代码控制工具栏操作
新增CraftingSystem,控制控制工具栏
public class CraftingSystem : MonoBehaviour { public GameObject craftingScreenUl; // 制作界面UI对象 public GameObject toolsScreenUl; // 工具界面UI对象 // 工具按钮 Button toolsBTN; [HideInInspector] public bool isOpen; // 是否打开制作系统界面 // 所有的蓝图 public static CraftingSystem Instance { get; set; } private void Awake() { if (Instance == null) { Instance = this; } else { Destroy(gameObject); } } void Start() { isOpen = false; toolsBTN = craftingScreenUl.transform.Find("背景").Find("工具按钮").GetComponent<Button>(); toolsBTN.onClick.AddListener(delegate { OpenToolsCategory(); }); } void OpenToolsCategory() { craftingScreenUl.SetActive(false); // 关闭制作界面 toolsScreenUl.SetActive(true); // 打开工具界面 } void Update() { if (Input.GetKeyDown(KeyCode.I)) { // 打开关闭制作界面 craftingScreenUl.SetActive(!isOpen); if (isOpen) toolsScreenUl.SetActive(false); // 关闭工具界面 isOpen = !isOpen; // 设置鼠标锁定模式为无锁定,允许鼠标在界面上移动 Cursor.lockState = (isOpen || InventorySystem.Instance.isOpen) ? CursorLockMode.None : CursorLockMode.Locked; } } }
修改MouseLook,控制相机视角
void FreeLook() { if(InventorySystem.Instance.isOpen || CraftingSystem.Instance.isOpen) return; //。。。 }
挂载代码,配置
效果
制作石斧
新增Blueprint,定义制作蓝图
public class Blueprint { public string itemName; // 蓝图对应的物品名称 public string Req1; // 需求1的物品名称 public string Req2; // 需求2的物品名称 public int Req1amount; // 需求1的数量 public int Req2amount; // 需求2的数量 public int numOfRequirements; // 需求的总数 // 构造函数 public Blueprint(string name, int reqNUM, string R1, int R1num, string R2, int R2num) { itemName = name; // 设置蓝图对应的物品名称 numOfRequirements = reqNUM; // 设置需求的总数 Req1 = R1; // 设置需求1的物品名称 Req1amount = R1num; // 设置需求1的数量 Req2 = R2; // 设置需求2的物品名称 Req2amount = R2num; // 设置需求2的数量 } }
修改InventorySystem,实现删除物品 更新库存列表功能
//添加物品 public void AddToInventory(string itemName) { //... ReCalculeList(); CraftingSystem.Instance.RefreshNeededItems(); } //删除物品 public void RemoveItem(string nameToRemove, int amountToRemove) { int counter = amountToRemove; // 计数器,表示还需要删除的数量 for (var i = slotList.Count - 1; i >= 0; i--) // 倒序遍历所有物品槽 { if (slotList[i].transform.childCount > 0) // 如果该槽有物品 { if (slotList[i].transform.GetChild(0).name == nameToRemove + "(Clone)" && counter != 0) // 如果该物品名称匹配且还需要删除的数量不为 0 { Destroy(slotList[i].transform.GetChild(0).gameObject); // 删除该物品 counter -= 1; // 计数器减 1 } } } ReCalculeList(); CraftingSystem.Instance.RefreshNeededItems(); } //更新库存列表 public void ReCalculeList() { itemList.Clear(); // 清空物品清单 foreach (GameObject slot in slotList) // 遍历所有的物品槽 { if (slot.transform.childCount > 0) // 如果该槽有物品 { string name = slot.transform.GetChild(0).name; // 获取物品名称,例如 "Stone (Clone)" string str2 = "(Clone)"; string result = name.Replace(str2, ""); // 去掉后缀 "(Clone)",例如 "Stone" itemList.Add(result); // 将物品名称添加到物品清单列表中 } } }
修改CraftingSystem
public Blueprint AxeBLP = new Blueprint("石斧", 2, "小石头", 2, "树枝", 2);//石斧制作蓝图 void Start() { isOpen = false; toolsBTN = craftingScreenUl.transform.Find("背景").Find("工具按钮").GetComponent<Button>(); toolsBTN.onClick.AddListener(delegate { OpenToolsCategory(); }); //斧头 AxeReq1 = toolsScreenUl.transform.Find("背景").Find("内容").Find("斧头").Find("材料1").GetComponent<TextMeshProUGUI>(); AxeReq2 = toolsScreenUl.transform.Find("背景").Find("内容").Find("斧头").Find("材料2").GetComponent<TextMeshProUGUI>(); craftAxeBTN = toolsScreenUl.transform.Find("背景").Find("内容").Find("斧头").Find("制作按钮").GetComponent<Button>(); craftAxeBTN.onClick.AddListener(delegate { CraftAnyltem(AxeBLP); }); } //制作事件 void CraftAnyltem(Blueprint blueprintToCraft) { InventorySystem.Instance.AddToInventory(blueprintToCraft.itemName); //按需求的总数,删除对应的物品 if (blueprintToCraft.numOfRequirements == 1) { InventorySystem.Instance.RemoveItem(blueprintToCraft.Req1, blueprintToCraft.Req1amount); } else if (blueprintToCraft.numOfRequirements == 2) { InventorySystem.Instance.RemoveItem(blueprintToCraft.Req1, blueprintToCraft.Req1amount); InventorySystem.Instance.RemoveItem(blueprintToCraft.Req2, blueprintToCraft.Req2amount); } } //刷新需要的物品 private void RefreshNeededItems() { int stone_count = 0; // 石头数量 int stick_count = 0; // 树枝数量 inventoryltemList = InventorySystem.Instance.itemList; // 获取物品清单 foreach (string itemName in inventoryltemList) // 遍历物品清单 { switch (itemName) { case "小石头": stone_count += 1; // 统计石头数量 break; case "树枝": stick_count += 1; // 统计树枝数量 break; } } // 更新需求文本 AxeReq1.text = "2 石头 [" + stone_count + "]"; // 显示需要的石头数量 AxeReq2.text = "2 树枝 [" + stick_count + "]"; // 显示需要的树枝数量 if (stone_count >= 2 && stick_count >= 2) { craftAxeBTN.gameObject.SetActive(true); // 激活制作斧头按钮 } else { craftAxeBTN.gameObject.SetActive(false); // 禁用制作斧头按钮 } }
效果