Unity中C# List RemoveAt异常:单次点击触发多次移除问题
Unity C# List 重复删除问题修复
问题根源
当生成随机索引(比如2)并触发chooseNpc事件后,所有预制体的NpcController都会执行NpcEvent判断:
- 第一个匹配索引的预制体执行删除操作后,List中原索引大于该值的元素会自动前移一位(比如原索引3变为2)
- 后续预制体执行
IndexOf时,会得到新的索引值,刚好等于未更新的randNpcValue,导致重复触发移动和删除逻辑
修正方案
将选中、移动、删除的逻辑统一放在ListController中处理,避免多个预制体同时判断索引,同时移除目标对象的事件监听防止后续误触发:
修改后的 ListController 代码
public class ListController : MonoBehaviour // 修正类名拼写错误 { public GameObject cubePrefab; private GameObject cubeInstance; public static List<GameObject> cubeList = new List<GameObject>(); public TextMeshProUGUI checkText; public static event Action chooseNpc; public static int randNpcValue; private void Start() { for(int i = 0; i < 5; i++) { cubeInstance = Instantiate(cubePrefab, new Vector3(i, -2, 0), Quaternion.identity); cubeList.Add(cubeInstance); } } public void CheckListText() { checkText.text = "Npc in list: " + cubeList.Count.ToString(); } public static void SelectRandomCube() { if(cubeList.Count == 0) return; // 空列表直接返回,避免报错 randNpcValue = Random.Range(0, cubeList.Count); var targetCube = cubeList[randNpcValue]; // 执行移动逻辑 targetCube.transform.localPosition = new Vector3(targetCube.transform.position.x, 2, 0); // 从列表移除 cubeList.RemoveAt(randNpcValue); Debug.Log($"Delete from list: {randNpcValue}"); // 移除目标对象的事件监听,防止后续触发 var npcController = targetCube.GetComponent<NpcController>(); if(npcController != null) { ListController.chooseNpc -= npcController.NpcEvent; } } }
简化后的 NpcController 代码
如果不需要其他事件逻辑,可移除删除和移动代码(仅保留必要的事件绑定,或直接移除该脚本):
public class NpcController : MonoBehaviour { void Start() { ListController.chooseNpc += NpcEvent; } private void NpcEvent() { // 这里可以保留其他需要针对选中对象执行的逻辑,比如播放动画等 // 移动和删除逻辑已移至ListController,无需在这里处理 } }
额外注意事项
- 修正了类名
ListCOntroller的拼写错误为ListController,避免潜在的命名问题 - 增加了空列表判断,防止
Random.Range传入无效范围导致报错 - 如果需要销毁预制体,可在
SelectRandomCube中添加Destroy(targetCube);语句
内容的提问来源于stack exchange,提问作者qwdza54
相关产品推荐
相关产品推荐

