aframe
aframe copied to clipboard
Animation hiccups when an object is removed from the DOM
Description: Small animation hiccups happen whenever an entity is removed from the dom with "removeChild"
NOTE: Jumps from one frame to another are expected, however sometimes those jumps make the positions mismatch the expected position, see example.
- A-Frame Version: 1.5.0
- Platform / Device: All (more notable on Mobile VR like Quest headsets)
- Reproducible Code Snippet or URL:
- https://glitch.com/edit/#!/quirky-royal-branch
Without investigating the particulars. In general you should avoid creating and destroying entities and reuse them to prevent unnecessary memory and other resource allocations. Can animate and reset the positions.
A THREE.js example for reference https://glitch.com/edit/#!/sequoia-global-dove?path=index.html%3A49%3A46
Thank you I assume this is not an a-frame issue, but a performance optimization issue then, I'll close it and dismiss it
I think we should still investigate what's the root cause. no reason I can see why animations shouldn't be always smooth
Thanks for the clear and concise glitch showing the issue @meduzo. I managed to find the root cause. The removal of the element happens while the scene is processing ticks, but the element's tick handlers are removed from the scene at that point as well. This can cause the scene to accidentally skip over some tick handlers, which for the animation component means it won't advance its animation for a frame.
I've created a PR that addresses this oversight: #5403
In the meantime as a crude workaround you can delay the removal by wrapping it in a setTimeout, like so:
setTimeout(() => {
this.parentNode.removeChild(this);
}, 0)
@mrxz thanks! animation is janky even in the three example:
https://glitch.com/edit/#!/sequoia-global-dove?path=index.html%3A49%3A46
There might be additional issues
With examples above notice that animation can be janky even when the application hits 60fps consistently. So wonder where is the jank coming from.
Found this https://bugs.chromium.org/p/chromium/issues/detail?id=1164435 but also see stutter in Safari that it's not chromium. Tried on Macbook Air M1. Safari on iOS feels smoother
@dmarcos I don't really see any jank in the three example. Only occasionally when it hits the bottom, but that's probably due to the setInterval not taking exactly 5000ms. Would be better to kick of the next animation cycle when the first one completes.
With Chrome I did notice that after a while the frame timings started to become inconsistent for brief periods (~1-2s at a time) resulting in slight judder, despite maintaining a steady 60fps. Wondering if it might be better to use the rAF timestamp to derive the delta instead of performance.now() as the former did maintain a virtually consistent 0.01667 throughout.
Came across this Codepen: https://codepen.io/joliss/pen/wWKGeV/
This seems to indicate that using the rAF timestamp results in more consistent frame pacing compared to performance.now(). Effect is even more pronounced on Chrome since it actually provides sub-millisecond precision. It seems that the rAF timestamp reflects the "true" frame time, whereas measuring with performance.now() includes scheduling delays, which can be inconsistent between frames.
@dmarcos Could you test if you see the same issue with this Glitch (using rAF timestamp instead of performance.now()): https://glitch.com/edit/#!/towering-sequoia-scarer
If that resolves it, this might be worth using as the source for the delta in A-Frame. Though it warrants more testing (WebXR sessions, more devices/browsers, low fps)
I think more or less the same. I'm not sure whether the issue is on our side or the browser updating the canvas. On chrome I usually have tons of tabs opened so might be a factor. To make sure is not our fault instead of visually it would be worth measuring frame time consistency. If we're hitting the numbers then it might be the browser.