Manim使用always_redraw循环添加多个VMobject仅显示1个如何解决
问题原因
这个现象是Python的迟绑定特性导致的:循环内定义的匿名函数/闭包捕获的是循环变量本身,而非迭代瞬间的变量值。等循环结束所有always_redraw绑定的更新逻辑都指向最后一次迭代的VMobject实例,因此仅单个对象正常显示。
修复方案
方案1:默认参数绑定迭代值(直接修复原有写法)
在always_redraw的匿名函数中加入默认参数,默认参数会在函数定义时完成求值,可以锁定当前迭代的VMobject实例:
# 错误写法示例 shapes = [Square(), Circle(), Triangle()] x = ValueTracker(0) for shape in shapes: # 所有匿名函数最终都引用最后一次迭代的shape always_redraw(lambda: shape.move_to([x.get_value(), 0, 0])) # 修正后写法 shapes = [Square(), Circle(), Triangle()] x = ValueTracker(0) for shape in shapes: # 用默认参数s绑定当前迭代的shape值 always_redraw(lambda s=shape: s.move_to([x.get_value(), 0, 0]))
方案2:单独绑定对象updater(更易维护)
放弃批量调用always_redraw,改为给每个VMobject单独绑定更新器,逻辑更清晰也更难踩闭包坑:
shapes = [Square(), Circle(), Triangle()] x = ValueTracker(0) for idx, shape in enumerate(shapes): def update_mob(mob, i=idx): mob.move_to([x.get_value() + i*2, 0, 0]) shape.add_updater(update_mob) add(shape)
方案3:VGroup统一管理更新(适合批量同逻辑对象)
如果所有对象的更新逻辑一致,可以用VGroup打包所有对象后绑定统一更新器,代码更简洁:
x = ValueTracker(0) shapes = VGroup(Square(), Circle(), Triangle()).arrange(RIGHT, buff=1) def update_group(group): for i, mob in enumerate(group): mob.move_to([x.get_value() + i*2, 0, 0]) shapes.add_updater(update_group) add(shapes)
注意事项
如果涉及大量对象的高频更新,优先使用updater方案而非多次调用always_redraw,前者性能表现更优,也更方便后续调试修改。
内容的提问来源于stack exchange,提问作者Moritz Groß
相关产品推荐
相关产品推荐

