Description
Description of bug / unexpected behavior
After running two consecutive ReplacementTransform
calls- first replacing a circle with a square, then that square with a triangle - the original circle and/or square sometimes remain in self.mobjects
, resulting in extra, empty shapes (“ghosts”) being rendered alongside the intended transform.
Expected behavior
Only one triangle instance should remain on‑screen after the two ReplacementTransform
calls, and self.mobjects
should contain exactly that single triangle.
How to reproduce the issue
Code for reproducing the problem
from manim import Scene, Circle, Square, Triangle, ReplacementTransform, FadeIn, MoveAlongPath, Line
from manim.utils.color.manim_colors import PINK, LIGHTER_GRAY, RED
from manim import RIGHT, LEFT, UP
class Test(Scene):
def construct(self):
circle = Circle(color=PINK, radius=4, fill_opacity=0).shift(LEFT)
square = Square(side_length=2, color=LIGHTER_GRAY).shift(UP)
triangle = Triangle(radius=3, color=RED).shift(RIGHT)
self.play(FadeIn(circle))
self.play(FadeIn(square))
self.play(FadeIn(triangle))
self.play(ReplacementTransform(circle, square))
self.play(ReplacementTransform(square, triangle))
triangle.set_fill(RED, opacity=0.5)
self.wait(2)
path = Line(RIGHT, LEFT)
self.play(MoveAlongPath(triangle, path))
self.wait(2)
# Inspect remaining mobjects
for obj in self.mobjects:
print(obj)
Triangle
Square
Triangle
Mobject
Mobject
Additional media files
Images/GIFs
Test.mp4
Logs
Terminal output
(manim) PS D:\Programming\manim-test> manim test.py Test -pql -v DEBUG
Manim Community v0.19.0
[05/04/25 22:19:22] DEBUG Hashing ... hashing.py:352
DEBUG Hashing done in 0.009381 s. hashing.py:364
DEBUG Hash generated : 1185818338_4190402543_223132457 hashing.py:367
INFO Animation 0 : Using cached data (hash : cairo_renderer.py:89
1185818338_4190402543_223132457)
DEBUG List of the first few animation hashes of the scene: cairo_renderer.py:98
['1185818338_4190402543_223132457']
DEBUG Hashing ... hashing.py:352
DEBUG Hashing done in 0.009456 s. hashing.py:364
DEBUG Hash generated : 624642324_537848572_4156405120 hashing.py:367
INFO Animation 1 : Using cached data (hash : cairo_renderer.py:89
624642324_537848572_4156405120)
DEBUG List of the first few animation hashes of the scene: cairo_renderer.py:98
['1185818338_4190402543_223132457', '624642324_537848572_4156405120']
DEBUG Hashing ... hashing.py:352
DEBUG Hashing done in 0.009287 s. hashing.py:364
DEBUG Hash generated : 624642324_2607346297_110000080 hashing.py:367
INFO Animation 2 : Using cached data (hash : cairo_renderer.py:89
624642324_2607346297_110000080)
DEBUG List of the first few animation hashes of the scene: cairo_renderer.py:98
['1185818338_4190402543_223132457', '624642324_537848572_4156405120',
'624642324_2607346297_110000080']
DEBUG Hashing ... hashing.py:352
DEBUG Hashing done in 0.010183 s. hashing.py:364
DEBUG Hash generated : 624642324_289194527_836597036 hashing.py:367
INFO Animation 3 : Using cached data (hash : 624642324_289194527_836597036) cairo_renderer.py:89
DEBUG List of the first few animation hashes of the scene: cairo_renderer.py:98
['1185818338_4190402543_223132457', '624642324_537848572_4156405120',
'624642324_2607346297_110000080', '624642324_289194527_836597036']
DEBUG Hashing ... hashing.py:352
DEBUG Hashing done in 0.008176 s. hashing.py:364
DEBUG Hash generated : 624642324_3194600842_1010701616 hashing.py:367
INFO Animation 4 : Using cached data (hash : cairo_renderer.py:89
624642324_3194600842_1010701616)
DEBUG List of the first few animation hashes of the scene: cairo_renderer.py:98
['1185818338_4190402543_223132457', '624642324_537848572_4156405120',
'624642324_2607346297_110000080', '624642324_289194527_836597036',
'624642324_3194600842_1010701616']
DEBUG Animation with empty mobject animation.py:190
DEBUG Hashing ... hashing.py:352
DEBUG Hashing done in 0.006768 s. hashing.py:364
DEBUG Hash generated : 624642324_2872842549_4071541655 hashing.py:367
INFO Animation 5 : Using cached data (hash : cairo_renderer.py:89
624642324_2872842549_4071541655)
DEBUG List of the first few animation hashes of the scene: cairo_renderer.py:98
['1185818338_4190402543_223132457', '624642324_537848572_4156405120',
'624642324_2607346297_110000080', '624642324_289194527_836597036',
'624642324_3194600842_1010701616']
DEBUG Hashing ... hashing.py:352
DEBUG Hashing done in 0.010292 s. hashing.py:364
DEBUG Hash generated : 624642324_3653221575_1206155369 hashing.py:367
INFO Animation 6 : Using cached data (hash : cairo_renderer.py:89
624642324_3653221575_1206155369)
DEBUG List of the first few animation hashes of the scene: cairo_renderer.py:98
['1185818338_4190402543_223132457', '624642324_537848572_4156405120',
'624642324_2607346297_110000080', '624642324_289194527_836597036',
'624642324_3194600842_1010701616']
DEBUG Animation with empty mobject animation.py:190
DEBUG Hashing ... hashing.py:352
DEBUG Hashing done in 0.008523 s. hashing.py:364
DEBUG Hash generated : 624642324_2872842549_3178527957 hashing.py:367
INFO Animation 7 : Using cached data (hash : cairo_renderer.py:89
624642324_2872842549_3178527957)
DEBUG List of the first few animation hashes of the scene: cairo_renderer.py:98
['1185818338_4190402543_223132457', '624642324_537848572_4156405120',
'624642324_2607346297_110000080', '624642324_289194527_836597036',
'624642324_3194600842_1010701616']
Triangle
Square
Triangle
Mobject
Mobject
INFO Combining to Movie file. scene_file_writer.py:739
DEBUG Partial movie files to combine (8 files): scene_file_writer.py:622
['D:\\Programming\\manim-test\\media\\videos\\test\\480p15\\partia
l_movie_files\\Test\\1185818338_4190402543_223132457.mp4',
'D:\\Programming\\manim-test\\media\\videos\\test\\480p15\\partial
_movie_files\\Test\\624642324_537848572_4156405120.mp4',
'D:\\Programming\\manim-test\\media\\videos\\test\\480p15\\partial
_movie_files\\Test\\624642324_2607346297_110000080.mp4',
'D:\\Programming\\manim-test\\media\\videos\\test\\480p15\\partial
_movie_files\\Test\\624642324_289194527_836597036.mp4',
'D:\\Programming\\manim-test\\media\\videos\\test\\480p15\\partial
_movie_files\\Test\\624642324_3194600842_1010701616.mp4']
INFO scene_file_writer.py:886
File ready at
'D:\Programming\manim-test\media\videos\test\480p15\Test.mp4'
INFO Rendered Test scene.py:255
Played 8 animations
[05/04/25 22:19:23] INFO Previewed File at: file_ops.py:237
'D:\Programming\manim-test\media\videos\test\480p15\Test.mp4'
System specifications
System Details
- OS: Windows 10 Education (10.0.19045 Build 19045)
- RAM: 16GB
- Python version (
python/py/python3 --version
): 3.12.10 - Installed modules (conda list):
# Name Version Build Channel
_openmp_mutex 4.5 2_gnu conda-forge
anyio 4.9.0 pyh29332c3_0 conda-forge
aom 3.9.1 he0c23c2_0 conda-forge
av 13.1.0 py312he67cb50_0 conda-forge
backports 1.0 pyhd8ed1ab_5 conda-forge
backports.tarfile 1.2.0 pyhd8ed1ab_1 conda-forge
beautifulsoup4 4.13.4 pyha770c72_0 conda-forge
brotli-python 1.1.0 py312h275cf98_2 conda-forge
bzip2 1.0.8 h2466b09_7 conda-forge
ca-certificates 2025.4.26 h4c7d964_0 conda-forge
cachecontrol 0.14.3 pyha770c72_0 conda-forge
cachecontrol-with-filecache 0.14.3 pyhd8ed1ab_0 conda-forge
cairo 1.18.4 h5782bbf_0 conda-forge
certifi 2025.1.31 pyhd8ed1ab_0 conda-forge
cffi 1.17.1 py312h4389bb4_0 conda-forge
charset-normalizer 3.4.2 pyhd8ed1ab_0 conda-forge
cleo 2.1.0 pyhd8ed1ab_1 conda-forge
click 8.1.8 pyh7428d3b_0 conda-forge
cloup 3.0.7 pyhd8ed1ab_0 conda-forge
colorama 0.4.6 pyhd8ed1ab_1 conda-forge
crashtest 0.4.1 pyhd8ed1ab_1 conda-forge
dav1d 1.2.1 hcfcfb64_0 conda-forge
decorator 5.2.1 pyhd8ed1ab_0 conda-forge
distlib 0.3.9 pyhd8ed1ab_1 conda-forge
dulwich 0.22.8 py312h2615798_0 conda-forge
exceptiongroup 1.2.2 pyhd8ed1ab_1 conda-forge
ffmpeg 7.1.1 gpl_hc27df84_704 conda-forge
filelock 3.18.0 pyhd8ed1ab_0 conda-forge
findpython 0.6.3 pyhff2d567_0 conda-forge
font-ttf-dejavu-sans-mono 2.37 hab24e00_0 conda-forge
font-ttf-inconsolata 3.000 h77eed37_0 conda-forge
font-ttf-source-code-pro 2.038 h77eed37_0 conda-forge
font-ttf-ubuntu 0.83 h77eed37_3 conda-forge
fontconfig 2.15.0 h765892d_1 conda-forge
fonts-conda-ecosystem 1 0 conda-forge
fonts-conda-forge 1 0 conda-forge
freetype 2.13.3 h57928b3_1 conda-forge
fribidi 1.0.10 h8d14728_0 conda-forge
gdk-pixbuf 2.42.12 hed59a49_0 conda-forge
glcontext 3.0.0 py312h275cf98_1 conda-forge
glib 2.84.1 he8f994d_1 conda-forge
glib-tools 2.84.1 h4394cf3_1 conda-forge
graphite2 1.3.13 h63175ca_1003 conda-forge
h11 0.16.0 pyhd8ed1ab_0 conda-forge
h2 4.2.0 pyhd8ed1ab_0 conda-forge
harfbuzz 11.1.0 h8796e6f_0 conda-forge
hpack 4.1.0 pyhd8ed1ab_0 conda-forge
httpcore 1.0.9 pyh29332c3_0 conda-forge
httpx 0.28.1 pyhd8ed1ab_0 conda-forge
hyperframe 6.1.0 pyhd8ed1ab_0 conda-forge
icu 75.1 he0c23c2_0 conda-forge
idna 3.10 pyhd8ed1ab_1 conda-forge
importlib-metadata 8.6.1 pyha770c72_0 conda-forge
importlib_resources 6.5.2 pyhd8ed1ab_0 conda-forge
intel-openmp 2024.2.1 h57928b3_1083 conda-forge
isosurfaces 0.1.2 pyhd8ed1ab_0 conda-forge
jaraco.classes 3.4.0 pyhd8ed1ab_2 conda-forge
jaraco.context 6.0.1 pyhd8ed1ab_0 conda-forge
jaraco.functools 4.1.0 pyhd8ed1ab_0 conda-forge
keyring 25.6.0 pyh7428d3b_0 conda-forge
lame 3.100 hcfcfb64_1003 conda-forge
lcms2 2.17 hbcf6048_0 conda-forge
lerc 4.0.0 h6470a55_1 conda-forge
libblas 3.9.0 31_h641d27c_mkl conda-forge
libcblas 3.9.0 31_h5e41251_mkl conda-forge
libdeflate 1.23 h76ddb4d_0 conda-forge
libexpat 2.7.0 he0c23c2_0 conda-forge
libffi 3.4.6 h537db12_1 conda-forge
libfreetype 2.13.3 h57928b3_1 conda-forge
libfreetype6 2.13.3 h0b5ce68_1 conda-forge
libgcc 14.2.0 h1383e82_2 conda-forge
libgd 2.3.3 h7208af6_11 conda-forge
libglib 2.84.1 hbc94333_1 conda-forge
libgomp 14.2.0 h1383e82_2 conda-forge
libhwloc 2.11.2 default_ha69328c_1001 conda-forge
libiconv 1.18 h135ad9c_1 conda-forge
libintl 0.22.5 h5728263_3 conda-forge
libintl-devel 0.22.5 h5728263_3 conda-forge
libjpeg-turbo 3.1.0 h2466b09_0 conda-forge
liblapack 3.9.0 31_h1aa476e_mkl conda-forge
liblzma 5.8.1 h2466b09_0 conda-forge
libogg 1.3.5 h2466b09_1 conda-forge
libopus 1.5.2 h2466b09_0 conda-forge
libpng 1.6.47 h7a4582a_0 conda-forge
librsvg 2.58.4 h5ce5fed_3 conda-forge
libsqlite 3.49.1 h67fdade_2 conda-forge
libtiff 4.7.0 h797046b_4 conda-forge
libusb 1.0.28 h2466b09_0 conda-forge
libvorbis 1.3.7 h0e60522_0 conda-forge
libwebp-base 1.5.0 h3b0e114_0 conda-forge
libwinpthread 12.0.0.r4.gg4f2fc60ca h57928b3_9 conda-forge
libxcb 1.17.0 h0e4246c_0 conda-forge
libxml2 2.13.7 h442d1da_1 conda-forge
libzlib 1.3.1 h2466b09_2 conda-forge
manim 0.19.0 pyh29332c3_0 conda-forge
manimpango 0.6.0 py312hd5ffd92_0 conda-forge
mapbox_earcut 1.0.3 py312hbaa7e33_1 conda-forge
markdown-it-py 3.0.0 pyhd8ed1ab_1 conda-forge
mdurl 0.1.2 pyhd8ed1ab_1 conda-forge
mkl 2024.2.2 h66d3029_15 conda-forge
moderngl 5.11.1 py312h72972c8_0 conda-forge
moderngl-window 3.1.1 pyh29332c3_1 conda-forge
more-itertools 10.7.0 pyhd8ed1ab_0 conda-forge
msgpack-python 1.1.0 py312hd5eb7cc_0 conda-forge
networkx 3.4.2 pyh267e887_2 conda-forge
numpy 2.2.5 py312h3150e54_0 conda-forge
openh264 2.6.0 hb17fa0b_0 conda-forge
openjpeg 2.5.3 h4d64b90_0 conda-forge
openssl 3.5.0 ha4e3fda_1 conda-forge
packaging 25.0 pyh29332c3_1 conda-forge
pango 1.56.3 h0c53d3b_1 conda-forge
pbs-installer 2025.4.9 pyhd8ed1ab_0 conda-forge
pcre2 10.45 h99c9b8b_0 conda-forge
pillow 11.1.0 py312h078707f_0 conda-forge
pip 25.1.1 pyh8b19718_0 conda-forge
pixman 0.46.0 had0cd8c_0 conda-forge
pkginfo 1.12.1.2 pyhd8ed1ab_0 conda-forge
platformdirs 4.3.7 pyh29332c3_0 conda-forge
poetry 2.1.2 pyh7428d3b_0 conda-forge
poetry-core 2.1.2 pyhd8ed1ab_0 conda-forge
pthread-stubs 0.4 h0e40799_1002 conda-forge
pycairo 1.28.0 py312h0cc4484_0 conda-forge
pycparser 2.22 pyh29332c3_1 conda-forge
pydub 0.25.1 pyhd8ed1ab_1 conda-forge
pyglet 2.1.6 pyhd8ed1ab_0 conda-forge
pyglm 2.8.2 py312hd5eb7cc_0 conda-forge
pygments 2.19.1 pyhd8ed1ab_0 conda-forge
pyproject_hooks 1.2.0 pyhd8ed1ab_1 conda-forge
pysocks 1.7.1 pyh09c184e_7 conda-forge
python 3.12.10 h3f84c4b_0_cpython conda-forge
python-build 1.2.2.post1 pyhff2d567_1 conda-forge
python-fastjsonschema 2.21.1 pyhd8ed1ab_0 conda-forge
python-installer 0.7.0 pyhff2d567_1 conda-forge
python_abi 3.12 7_cp312 conda-forge
pywin32-ctypes 0.2.3 py312h2e8e312_1 conda-forge
pyyaml 6.0.2 py312h31fea79_2 conda-forge
rapidfuzz 3.13.0 py312h275cf98_0 conda-forge
requests 2.32.3 pyhd8ed1ab_1 conda-forge
requests-toolbelt 1.0.0 pyhd8ed1ab_1 conda-forge
rich 14.0.0 pyh29332c3_0 conda-forge
scipy 1.15.2 py312h451d5c4_0 conda-forge
screeninfo 0.8.1 py312h2e8e312_2 conda-forge
sdl2 2.32.54 he0c23c2_0 conda-forge
sdl3 3.2.10 he0c23c2_1 conda-forge
setuptools 80.1.0 pyhff2d567_0 conda-forge
shellingham 1.5.4 pyhd8ed1ab_1 conda-forge
skia-pathops 0.8.0.post2 py312hd5eb7cc_0 conda-forge
sniffio 1.3.1 pyhd8ed1ab_1 conda-forge
soupsieve 2.5 pyhd8ed1ab_1 conda-forge
srt 3.5.3 py312h2e8e312_0 conda-forge
svgelements 1.9.6 pyhd8ed1ab_0 conda-forge
svt-av1 3.0.2 he0c23c2_0 conda-forge
tbb 2021.13.0 h62715c5_1 conda-forge
tk 8.6.13 h5226925_1 conda-forge
tomli 2.2.1 pyhd8ed1ab_1 conda-forge
tomlkit 0.13.2 pyha770c72_1 conda-forge
tqdm 4.67.1 pyhd8ed1ab_1 conda-forge
trove-classifiers 2025.5.1.12 pyhd8ed1ab_0 conda-forge
typing-extensions 4.13.2 h0e9735f_0 conda-forge
typing_extensions 4.13.2 pyh29332c3_0 conda-forge
tzdata 2025b h78e105d_0 conda-forge
ucrt 10.0.22621.0 h57928b3_1 conda-forge
urllib3 2.4.0 pyhd8ed1ab_0 conda-forge
vc 14.3 h2b53caa_26 conda-forge
vc14_runtime 14.42.34438 hfd919c2_26 conda-forge
virtualenv 20.30.0 pyhd8ed1ab_0 conda-forge
vs2015_runtime 14.42.34438 h7142326_26 conda-forge
watchdog 6.0.0 py312h2e8e312_0 conda-forge
wheel 0.45.1 pyhd8ed1ab_1 conda-forge
win_inet_pton 1.1.0 pyh7428d3b_8 conda-forge
x264 1!164.3095 h8ffe710_2 conda-forge
x265 3.5 h2d74725_3 conda-forge
xorg-libice 1.1.2 h0e40799_0 conda-forge
xorg-libsm 1.2.6 h0e40799_0 conda-forge
xorg-libx11 1.8.12 hf48077a_0 conda-forge
xorg-libxau 1.0.12 h0e40799_0 conda-forge
xorg-libxdmcp 1.1.5 h0e40799_0 conda-forge
xorg-libxext 1.3.6 h0e40799_0 conda-forge
xorg-libxpm 3.5.17 h0e40799_1 conda-forge
xorg-libxt 1.3.1 h0e40799_0 conda-forge
yaml 0.2.5 h8ffe710_2 conda-forge
zipp 3.21.0 pyhd8ed1ab_1 conda-forge
zstandard 0.23.0 py312h4389bb4_2 conda-forge
zstd 1.5.7 hbeecb71_2 conda-forge
Additional comments
Discord help link
Suggestions:
To the best of my knowledge, the issue arises because ReplacementTransform
always invokes the scene’s replace logic, which unconditionally inserts the target mobject at the source’s position - even if that target is already present - then removes only the source. This can leave behind a duplicate reference or the original target, producing “ghost” shapes after the animation .
A straightforward remedy would be to adjust ReplacementTransform
so that it:
- Detects Existing Targets
Before performing any insertion, check whethertarget_mobject
is already inscene.mobjects
. - Skips Redundant Inserts
If the target is present, only removes thesource_mobject
from the scene, rather than inserting the target again. - Falls Back Gracefully
If the target isn’t yet on-screen, proceed with the normal replace behaviour (insert + remove) so nothing else changes.
By doing this, after the transform finishes there will only ever be one instance of the target - no leftover “ghost” copies remain.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status