Unity C#对象池方法执行完毕后List被清空问题求助
解决Unity对象池pooledObjects列表被清空的问题
我来帮你排查和修复这个问题,你的对象池基础逻辑没问题,但列表被清空大概率是几个常见的Unity开发坑导致的,咱们一步步来:
1. 修复单例实现,避免跨场景或多实例导致的列表丢失
你的单例代码没有做重复实例检查,也没标记对象池为跨场景保留,这会引发两个问题:
- 场景切换时,对象池所在GameObject被销毁,新场景的ObjectPool重新初始化,旧的
pooledObjects列表直接丢失 - 场景中存在多个ObjectPool实例时,后面的实例会覆盖单例引用,新实例的
pooledObjects可能还没完成初始化
修改Awake方法:
void Awake() { if (ShareInstance == null) { ShareInstance = this; DontDestroyOnLoad(gameObject); // 让对象池跨场景保留 } else { Destroy(gameObject); // 销毁重复实例,避免冲突 } }
2. 避免Unity序列化意外覆盖列表
你的pooledObjects是公共字段,Unity会对公共字段做序列化处理。如果Inspector里这个列表是空的,或者序列化过程中被意外重置,可能干扰Start里的初始化逻辑。建议改成私有字段并添加序列化标签,既保留Inspector可见性,又避免外部意外修改:
[SerializeField] private List<GameObject> pooledObjects; public GameObject objectToPool; public int amountToPool;
3. 追踪列表的修改来源
有可能其他脚本不小心调用了pooledObjects.Clear()或者把它赋值为null。你可以给列表加一个带日志的属性,精准定位修改来源:
private List<GameObject> _pooledObjects; [SerializeField] public List<GameObject> pooledObjects { get => _pooledObjects; set { Debug.LogWarning($"pooledObjects被修改,调用栈:\n{new System.Diagnostics.StackTrace()}"); _pooledObjects = value; } }
这样一旦有代码修改这个列表,控制台会打印调用栈,帮你快速找到问题代码。
4. 完善GetPooledObject方法的未完成逻辑
你的GetPooledObject方法最后return...没写完,这会导致编译错误,甚至运行时异常,可能间接引发列表异常。补上扩容逻辑,当没有可用对象时自动创建新对象加入池:
public GameObject GetPooledObject() { // 遍历寻找未激活的可用对象 for (int i = 0; i < pooledObjects.Count; i++) { if (!pooledObjects[i].activeInHierarchy) { return pooledObjects[i]; } } // 没有可用对象时,实例化新对象加入池 GameObject obj = Instantiate(objectToPool); obj.SetActive(false); pooledObjects.Add(obj); return obj; }
5. 确认对象回收逻辑正确
确保所有从池里取出的对象,使用完毕后是调用SetActive(false)放回池,而不是Destroy()。如果调用了Destroy(),对象会被销毁,虽然不会直接清空列表,但可能引发后续逻辑异常,间接导致列表被修改。
按照上面的步骤修改后,应该就能解决列表被清空的问题了。
内容的提问来源于stack exchange,提问作者hinch
相关产品推荐
相关产品推荐

