Skip to content

MLR109: Updater order creates a definite one-frame lag

qual reports MLR109 when one leaf mobject updater directly feeds driver.get_center() into a geometry mutation, but the driver is a later Scene root whose own updater changes geometry from dt or another proven frame-varying read.

  • Default severity: warning
  • Minimum confidence: medium
  • Implementation phase: 4
  • Fix: none (suggests Scene order or one combined updater)

Scene.update_mobjects walks top-level roots in Scene order. Each leaf runs all of its updaters before the next root starts, so a follower before its driver reads the driver's state from the preceding frame.

The initial proof is intentionally narrow: both objects must have exact Manim kinds and be singleton, active top-level leaf roots during a positive dynamic wait; root order and the lexical driver binding must be exact; the reader must be a lambda with the direct mob.move_to(driver.get_center()) dependency; and the writer's complete write channels must include points. Named callbacks, groups, branches, composite getter expressions, static waits, and unknown bindings stay silent.

Wrong:

follower.add_updater(lambda mob: mob.move_to(driver.get_center()))
driver.add_updater(lambda mob, dt: mob.shift(RIGHT * dt))
self.add(follower, driver)  # reader runs first
self.wait(2)

Right:

self.add(driver, follower)  # writer runs first
self.wait(2)