如何向Pymunk碰撞处理器传递数据?解决数组更新报错问题
在Pymunk的separate碰撞处理器中正确传入并更新数组的方法
核心问题分析
你遇到的“set change in size iteration”错误,本质是在遍历集合(或列表)的同时直接修改其长度导致的。另外使用全局数组particles不仅代码耦合度高,也容易引发这类遍历修改冲突,正确的做法是通过Pymunk碰撞处理器的data参数传入数组,再安全地更新它。
解决方案步骤
1. 通过data参数传入数组,替代全局变量
注册碰撞处理器时,将particles和temperature等需要的参数作为data传入,这样在处理器函数中可以直接获取,无需依赖全局变量:
# 注册碰撞处理器并传入数据 handler = space.add_collision_handler(碰撞类型1, 碰撞类型2) handler.separate = self.remove_particle1 # 将需要的变量存入handler的data字典 handler.data["particles"] = particles handler.data["temperature"] = temperature
2. 安全更新数组:先收集待移除元素,再批量处理
不管particles是列表还是集合,都不要在遍历过程中直接修改原容器。先把需要移除的元素收集到临时列表,再一次性移除,避免遍历冲突:
def remove_particle1(self, arbiter, space, data): particle1_shape = arbiter.shapes[0] particle2_shape = arbiter.shapes[1] # 从data中取出需要的变量 particles = data["particles"] temperature = data["temperature"] if temperature > 50: # 收集所有需要移除的粒子 to_remove = [] for particle in particles: if particle.body in (particle1_shape.body, particle2_shape.body): to_remove.append(particle) # 批量移除粒子 for particle in to_remove: particles.remove(particle) # 从物理空间中移除对应的形状和刚体 space.remove(particle1_shape, particle1_shape.body) space.remove(particle2_shape, particle2_shape.body)
补充说明
- 如果
particles是集合类型,批量移除可以用particles.difference_update(to_remove),效率更高;如果是列表,用上述循环remove即可(注意列表的remove是按元素值匹配,确保元素可唯一识别)。 - 始终通过
data传递碰撞处理器需要的外部变量,避免全局变量带来的耦合和不可预见的问题。
内容的提问来源于stack exchange,提问作者MatthewO
相关产品推荐
相关产品推荐

