Unity运行时Update中如何按需更新List避免内存膨胀卡顿?
方案合理性判断
重新实例化List的方案本身完全成立
你遇到的卡顿根源是:每帧调用AddRange时没有清空原有数据,List会无限制累积历史每一帧抓取的所有LineRenderer坐标点,内存占用、后续遍历成本会随运行时间线性增长,最终触发卡顿。
你想到的「每次Update前重新实例化List」的逻辑,本质是让lineRendererPositions始终只存储当前帧的LineRenderer世界坐标点集合,没有冗余历史数据,从根源解决了List膨胀的问题。
- 这个方案的GC开销极低:Vector3是值类型,重新实例化List的内存分配成本远低于无限制累积数据带来的性能损耗,正常项目运行中完全可以用,不需要为了微量GC刻意规避
- 如果你本来的需求就是每帧获取最新的LineRenderer点集,这个方案已经完全满足要求,不需要额外写复杂的变化判断逻辑
什么时候需要加「内容不一致才更新」的判断
如果你的需求是仅当LineRenderer的点集发生实际变化时,才刷新List缓存,不需要每帧都拿最新数据,那才适合加对比逻辑,平白写逐点对比反而会增加不必要的CPU开销。
这类场景下的对比逻辑不需要写得太复杂,按优先级判断就行:
- 第一步先对比长度:新拿到的点数组长度和现有List的Count不相等,直接判定点集发生了变化,直接重新赋值List即可,这一步判断的成本几乎可以忽略
- 长度一致的情况下再做逐点校验:注意Vector3是浮点数,对比时要加极小的精度容差(比如0.0001),避免浮点计算精度误差导致的误判;只要任意一个点和List中对应位置的坐标差超过容差,就判定内容变化,重新赋值即可
- 所有点都校验完成、没有发现差异的话,直接跳过更新逻辑就行
可以参考的实现代码:
private void Update() { Vector3[] currentWorldPoints = GetLinePointsInWorldSpace(); // 长度不一致直接判定点集变化 if (currentWorldPoints.Length != lineRendererPositions.Count) { lineRendererPositions = new List<Vector3>(currentWorldPoints); return; } // 长度一致逐点校验变化 bool isPointSetChanged = false; for (int i = 0; i < currentWorldPoints.Length; i++) { // 加入精度容差避免浮点误差 if (Vector3.Distance(currentWorldPoints[i], lineRendererPositions[i]) > 0.0001f) { isPointSetChanged = true; break; } } if (isPointSetChanged) { lineRendererPositions = new List<Vector3>(currentWorldPoints); } }
额外注意点
- 不要为了“减少GC”刻意用
Clear()清空List再AddRange:这种写法和重新实例化List的效果差不多,但Clear()不会自动收缩List的原有容量,如果你的LineRenderer点数量波动很大(比如之前存过1000个点,后来只有3个点),这种写法反而会长期占用不必要的内存 - 如果业务逻辑就是每帧都要用到最新的LineRenderer点集,完全不需要做逐点对比,直接每帧重新赋值List即可,多余的对比逻辑反而会平白增加CPU占用
内容的提问来源于stack exchange,提问作者Daniel Lip
相关产品推荐
相关产品推荐

