Unity游戏物品栏刷新性能优化求助:批量销毁重建致卡顿
Unity物品栏UI刷新性能优化方案
核心优化思路
放弃全量销毁重建的逻辑,改为复用已有UI槽位+仅更新状态变化的槽位,同时减少不必要的内存分配与GC触发。
具体实现步骤
1. 缓存槽位UI与状态记录
先定义两个变量,分别缓存已创建的UI槽位,以及每个槽位的上一次状态(用于对比是否需要更新):
// 缓存已生成的物品槽UI实例 private List<InventoryItemUI> _cachedSlots = new List<InventoryItemUI>(); // 记录每个槽位的上一次状态(物品ID、数量),用于判断是否需要更新 private Dictionary<int, (int itemId, int count)> _lastSlotStates = new Dictionary<int, (int, int)>();
2. 优化刷新逻辑
替换原有的Redraw方法,仅做必要的UI调整与更新:
private void Redraw() { int inventorySize = selectedInventory.GetSize(); // 调整槽位数量:复用已有,补充不足,清理多余 // 移除超出当前物品栏大小的槽位 while (_cachedSlots.Count > inventorySize) { var extraSlot = _cachedSlots[^1]; Destroy(extraSlot.gameObject); _cachedSlots.RemoveAt(_cachedSlots.Count - 1); _lastSlotStates.Remove(_cachedSlots.Count); } // 补充不足的槽位 while (_cachedSlots.Count < inventorySize) { var newSlotObj = Instantiate(InventoryItemPrefab, transform); var slotUI = newSlotObj.GetComponent<InventoryItemUI>(); _cachedSlots.Add(slotUI); // 初始化当前槽位的状态记录 var currentItem = selectedInventory.GetItemAt(_cachedSlots.Count - 1); var initialState = (currentItem?.Id ?? -1, currentItem?.Count ?? 0); _lastSlotStates[_cachedSlots.Count - 1] = initialState; slotUI.Setup(selectedInventory, _cachedSlots.Count - 1); } // 仅更新状态发生变化的槽位 for (int i = 0; i < inventorySize; i++) { var currentItem = selectedInventory.GetItemAt(i); var currentState = (currentItem?.Id ?? -1, currentItem?.Count ?? 0); // 状态未变化则跳过更新 if (_lastSlotStates.TryGetValue(i, out var lastState) && lastState == currentState) { continue; } // 更新槽位UI _cachedSlots[i].Setup(selectedInventory, i); // 更新状态记录 _lastSlotStates[i] = currentState; } }
3. 内存与GC优化补充
- 避免频繁销毁创建:如果槽位数量波动大,建议用对象池管理闲置槽位——销毁时改为禁用对象并存入池,需要时从池取出激活,彻底避免
Instantiate/Destroy带来的GC开销。 - 按需触发刷新:不要主动轮询调用
Redraw,而是监听物品栏的事件(如物品添加、移除、数量变更),仅在事件触发时执行刷新。 - 缓存资源:在
Setup方法中避免重复加载物品图标等资源,提前缓存所有物品的Sprite、材质等资源,复用已有实例。 - 谨慎触发GC:Unity的GC会自动处理内存,除非出现内存异常,否则不要主动调用
GC.Collect(),建议在场景切换、加载间隙等合适时机调用。
内容的提问来源于stack exchange,提问作者Bahaa Soliman
相关产品推荐
相关产品推荐

