v9: Proposal to revamp the frameloop
krispya opened this issue · 0 comments
Problem
Working on the editor, we came across a need to suspend all R3F updates, but this was very hard to do in v8 and required manually manipulating internal states. On top of that, the THREE.Clock
is deeply flawed and cannot provide deterministic time or even pause, not to mention the known issues of only being able to call getElapsedTime()
once per rAF. As well, updates in the loop are leaky. Some updates will fire even if render does not, and it isn't clear which and why.
Propsoal
Timer
To start, we will use Mugen's Timer
, ported to three-stdlib
, instead of THREE.Clock
. This changes some of the APIs slightly but allows for many benefits such as time scaling, proper get functions, deterministic time and even pausing the timer when tabbed away.
Unity loops and effects
R3F effects currently fire every tick even if the frameloop
is set to never
. Effects should be deprecated and automatically dumped into the corresponding stages, Early
, Late
and After
. The frameloop
settings will be changed to top level instead of per root. This will avoid really confusing situations where different roots have different render settings, but the effects still fire on all of them every update.
Frameloop never
revamp
Frameloop never
will be changed to fit more common workflows. Currently it only skips render()
calls with advance()
taking a timestamp to produce a delta. Instead, it will now pause the entire loop so no logic runs at all (even effects) unless advance()
is called. advance()
will now take a delta and advance the app by that delta each call. This will allow applications like the editor to manipulate the loop for debugging purposes as well as allow for animation unit tests.
Update Stages
to use Timer
.
Right now all Stages
maintain their own time. Putting it in one place helps lockstep them. One change that would need to be made for this is either make it so that all FixedStages
use the same fixed step -- like Unity -- or allow Timer
to keep multiple fixed steps of time. I'm leaning toward the later since there are some useful cases for having multiple fixed steps, such as putting different systems on different update schedules.