Unity中Crafting System合成系统无报错无法运行问题排查
Unity 简易Crafting合成系统无报错失效修复
核心故障原因
代码无语法报错但功能失效是4处逻辑问题导致,均属于静默失效类问题,不会主动抛出运行时错误:
- 索引使用错误:内层匹配循环中错误使用背包遍历索引
z去取配方需求数组Item的元素,配方需求数组的正确遍历索引是外层循环的i,索引错位直接导致匹配逻辑完全失效。 - 组件类型不匹配:项目使用
SCItem类型的ScriptableObject存储物品数据,但代码中获取物品组件时写的是GetComponent<Item>(),取到的组件永远为null,和SCItem类型的配方数据对比永远返回false。 - 重复计数漏洞:原有逻辑没有标记已匹配的背包物品,当背包内仅存在1个需求材料时,会被多次循环计数,导致材料数量不足时也会误判为满足合成条件。
- 缺失合法性校验:代码没有对关键引用(ItemManager、成品预制体、配方数组长度)做判空和配置校验,配置漏拖、对象找不到时会直接静默退出逻辑,没有任何提示。
Inspector配置参考

修复后完整代码
public class CraftingItem: MonoBehaviour { public int RequiredItems; public SCItem[] RequiredItemList; private Transform itemManagerTransform; public GameObject FinishItem; private readonly List<SCItem> _inventoryItemCache = new List<SCItem>(); public void Start(){ GameObject itemManagerGo = GameObject.FindWithTag("ItemManager"); if (itemManagerGo != null) { itemManagerTransform = itemManagerGo.transform; } // 配置错误时直接打印日志,避免静默失效 if (RequiredItemList.Length != RequiredItems) { Debug.LogError($"合成配置错误:{gameObject.name}的需求物品数量与配方数组长度不一致", this); } } public void CheckForRequiredItems(){ // 前置校验不满足直接返回 if (itemManagerTransform == null || FinishItem == null || RequiredItemList.Length != RequiredItems) { return; } int itemsInManager = itemManagerTransform.childCount; if(itemsInManager < RequiredItems) return; // 刷新当前背包物品缓存 _inventoryItemCache.Clear(); for(int z = 0; z < itemsInManager; z++){ // 替换为你物品预制体上实际挂的、持有SCItem引用的组件名 ItemSlot itemOnPlayer = itemManagerTransform.GetChild(z).GetComponent<ItemSlot>(); if (itemOnPlayer != null && itemOnPlayer.itemData != null) { _inventoryItemCache.Add(itemOnPlayer.itemData); } } int matchedCount = 0; List<SCItem> usedItems = new List<SCItem>(); // 遍历所有需求材料 for(int i = 0; i < RequiredItems; i++){ SCItem target = RequiredItemList[i]; // 找背包里未被使用的对应材料 for(int z = 0; z < _inventoryItemCache.Count; z++){ if(_inventoryItemCache[z] == target && !usedItems.Contains(_inventoryItemCache[z])){ matchedCount++; usedItems.Add(_inventoryItemCache[z]); break; } } } if(matchedCount >= RequiredItems){ Instantiate(FinishItem, transform.position, transform.rotation); // 若需要合成后消耗材料,在此处遍历usedItems对应销毁背包内的物品物体即可 } } }
适配说明
代码中
ItemSlot为示例组件名,你需要将其替换为自己项目中实际挂载在背包物品物体上、持有SCItem类型数据引用的MonoBehaviour组件名,确保能正确读取到每个背包物品对应的ScriptableObject数据。配置时需保证RequiredItems数值与RequiredItemList数组长度一致,数组内按需求拖入对应材料的SCItem资产即可。
内容的提问来源于stack exchange,提问作者BayEggex
相关产品推荐
相关产品推荐

