Fusion
Fusion copied to clipboard
Ability to delay state changes
For an upcoming project, I want all of my components to be on the same Spring but with a different delay so they don't all show up at the exact same time. I'm trying to make it similar to what Super Mario Maker 2 does in Network Play when revealing who you're playing with.
https://user-images.githubusercontent.com/13684891/138526714-eea980fe-5a93-4449-be29-bdaacf3a8d4d.MOV
Perhaps this could be implemented with an optional delay argument on the Spring:get() method?
This is definitely something we should look into! To keep it general though, we should be looking for a general solution for delaying not just Springs, but any kind of state change we might want to delay.
To that end, we could possibly implement an object like this, which exactly follows the value of another state object, but which delays all changes by some length of time:
local original = State(1)
local delayed = Delay(original, 2) -- delayed version of `original` by 2 seconds
print(original:get(), delayed:get()) -- 1 1
original:set(6)
print(original:get(), delayed:get()) -- 6 1
wait(2) -- 2 seconds later...
print(original:get(), delayed:get()) -- 6 6
This would be generally useful outside of tweens and springs for all sorts of delay-related use cases - we could even allow the delay time to be controlled by a state object, fitting in perfectly with the way other animation primitives work!
Approved for a future version of Fusion
If the original state changes, and then changes again before the delayed state finishes it's delay, will the delayed state only update once with the latest state at the end or start a new delay for every time the original state changes?
Because I feel like both would be useful in separate scenarios.
will the delayed state only update once with the latest state at the end
This sounds more like a debounce than a delay, but perhaps this could be an option.
After opening #94 with a working implementation of delay objects as described in this issue its clear there are a few more design choices that need to be considered.
-
Given the following occurs: i. Delay object exists with follower state of "?" and duration state of 3 ii. Delay follower state changes to "A" (delay object is now "active") iii. Delay duration state changes to 5 Does the active delay object use the new duration state of 5 or the initial state of 3?
-
Given the following occurs: i. Delay object exists and is active ii. Delay follower state changes before delay reaches its goal state Should delay only use the most recent follower state or keep track of previous goals and durations as well?
-
Should delay duration be allowed to be a state or should it just be a constant? If it remains as a constant we solve the first problem and the overall functionality of delay is more straightforward.
I'd say this is how Delay should work:
Delay will always have the value that the FollowerState did have [duration] time ago
If the duration is constant, this can be simple: task.delay
when FollowerState changes, and set the Delay's value in the callback.
If the duration is a State, this needs thought because the values of FollowerState need to be kept track of. By setting DurationState to a higher value than the time past since FollowerState last changed, the Delay would have to revert to a previous value of FollowerState to ensure correct behaviour. But, does this make sense? And is it realistic to implement? How far would Delay remember the FollowerState values? There needs to be a limit on Duration, otherwise the memory for Delay would get excessively big.
Yep and I think that functionality makes sense and is what users expect when/if they use Delay()
. While I believe that accepting state objects as a duration is inline with the rest of Fusion (e.g. springs), I think constants produce less issues and will provide the desired functionality.
I would love to hear more opinions on this though. We would appreciate your input on this @Elttob.
Good points - I also agree with having Delay(x, n) always equal to the value of x at n seconds in the past.
I think it'd be safest to start with constant values only while we figure out if it is viable to implement a variable delay. I imagine variable delay would be useful e.g. when introducing reduced motion accessibility settings, but we'd need some way of limiting the memory usage to something predictable
2d555a7 introduces a constant duration alongside the other functionality described here.