Unity for循环访问已销毁GameObject触发索引越界解决方案
索引越界问题根因
报错和你加的null判断逻辑无关,是三处代码逻辑错误直接导致的:
- C#数组索引从0开始计数,有效索引范围是
0 到 数组长度-1,你写的for循环判定条件为i <= balls.Length,当i自增到和数组长度相等时,访问balls[i]必然触发索引越界 - for循环结构本身会在每次迭代结束后自动执行
i++,你在if判断块内又手动写了一次i++,相当于每次处理一个球就给i加2,不仅会漏掉一半待处理的球,还会让i更快超出数组的有效索引范围 - 循环开始时调用
FindObjectsOfType<Ball>()拿到的是执行瞬间的所有球对象快照,循环过程中CallM3x()新生成的球不会被加入这个数组,中途销毁球只会让数组对应位置的引用变为null,不会改变数组本身的固定长度,你写的null校验逻辑本身没有问题,但根本拦不住前两个错误引发的索引溢出。
修复代码
先把球数上限判断移到循环外,避免无意义的循环执行,再修正循环条件、删掉多余的自增逻辑即可:
// 先校验总球数上限,达到阈值直接终止逻辑 if (FindObjectsOfType<Ball>().Length >= 1000) { return; } // 拉取执行瞬间所有存活的球对象 Ball[] balls = FindObjectsOfType<Ball>(); // 修正循环条件:i严格小于数组长度,去掉多余的手动i++ for (int i = 0; i < balls.Length; i++) { // 跳过循环中途被销毁的球 if (balls[i] == null) { continue; } // 触发多球增殖逻辑 balls[i].CallM3x(); }
优化提示:
FindObjectsOfType是全局查找API,频繁调用性能开销很高。可以做一个简易的全局球管理器,用List<Ball>动态维护存活球列表,球生成时加入列表、销毁时移出列表,后续直接遍历这个列表即可,不需要每次全局查找。
内容的提问来源于stack exchange,提问作者Ali Nabel
相关产品推荐
相关产品推荐

