Unity刷新UI列表时如何删除Instantiate生成的克隆GameObject
问题原因
你当前的代码没有对动态生成的克隆按钮做单独的标记和缓存,刷新UI时无法区分模板按钮和动态生成的商品按钮,自然没法精准删除旧的克隆对象;另外原代码里销毁prefab的逻辑如果指向克隆用的模板按钮,会导致后续刷新找不到克隆源。
实现方案
用专门的列表缓存所有动态生成的按钮,每次调用DrawUI生成新按钮前,先把缓存里的旧按钮全部销毁,再生成新的按钮存入缓存即可。
- 先在当前类里添加成员变量,专门存储动态生成的商品按钮:
using System.Collections.Generic; // 引入List所需的命名空间 // 类内部成员变量 private List<GameObject> spawnedCarButtons = new List<GameObject>();
- 修改DrawUI方法,在生成新按钮前增加清理旧UI的逻辑,同时修正原代码里误删模板、索引赋值的bug:
void DrawUI() { // 清理上一轮生成的所有旧商品按钮 foreach (GameObject oldButton in spawnedCarButtons) { if (oldButton != null) { Destroy(oldButton); } } spawnedCarButtons.Clear(); // 建议后续把模板按钮拖成序列化字段单独引用,不要靠GetChild(0)获取,避免误删 GameObject buttonTemplate = transform.GetChild(0).gameObject; GameObject spawnedBtn; int carCount = allCars.Length; for (int i = 0; i < carCount; i++) { spawnedBtn = Instantiate(buttonTemplate, transform); spawnedCarButtons.Add(spawnedBtn); // 新生成的按钮加入缓存列表 spawnedBtn.transform.Find("name").GetComponent<Text>().text = allCars[i].carName; spawnedBtn.transform.Find("type").GetComponent<Text>().text = allCars[i].type; Text priceText = spawnedBtn.transform.Find("price").GetComponent<Text>(); int carPrice = int.Parse(allCars[i].price); priceText.text = carPrice + "€"; if (balance < carPrice) { priceText.color = Color.red; } else { priceText.color = new Color32(53, 140, 3, 255); } spawnedBtn.GetComponent<Button>().AddEventListener(i, OpenBuyDialog); // 注意:原代码循环内直接给itemIndex赋值会有索引覆盖bug,所有按钮点击后只会拿到最后一个商品的索引,不要用全局变量存循环索引 } // 不要销毁模板按钮!保持隐藏即可,否则下次刷新没有克隆源 buttonTemplate.SetActive(false); }
补充优化点
- 最好把克隆用的按钮模板移出动态生成列表的父节点,在Inspector中给脚本加
[SerializeField] private GameObject carButtonTemplate;字段,直接拖拽模板赋值,模板默认设为隐藏,避免后续遍历父节点子物体时误删模板 - 价格解析、组件获取的逻辑可以提出来复用,避免重复调用GetComponent、Parse增加不必要的性能开销
- 用户购买完成后直接调用
DrawUI()即可,方法会自动清理旧列表、基于最新数据生成新的商品按钮
内容的提问来源于stack exchange,提问作者ViiperCoding
相关产品推荐
相关产品推荐

