I feel like I’m trying to pick at a problem with a very specific and unusual solution, so might as well ask before I introduce some needs to do some tragic refactoring.
Say I want a menu where, when entered, it slides and fades in, and I want to accomplish this through a tween since that seems like the obvious way and can account for differences like resolution/aspect ratio differences (as well as in general be more convenient than an AnimationPlayer), so the function that opens the menu sets up some preliminary information on the menu, then runs the tween that brings the menu in while awaiting for it to be complete.
Then, I want to make my menus feel better and more interactive, so I want the player to be able to further interact with or cancel out of a menu even as it is sliding/fading in. As tweens are created on runtime, this is not so easy. My idea around this was a two-step process:
Declare the tween outside of the function as a script variable, but create the tween on the variable during the function itself
Create a function in my UI tool singleton that takes a tween, checks if it is running, and if so, then stop it.
I could then call the tool function whenever I needed to skip over or cancel a tween by simply calling it on the script variable in another function (such as when exiting a menu). The issue with this is that as it stops the tween, the tween can no longer emit the finished signal (and trying to have the tween emit it manually in the tool function does not trigger the await), so the function simply turns into a memory leak awaiting a signal that is not coming. It doesn’t matter if the rest of the function happens or doesn’t happen as either case can be dealt with, but the memory leak itself is an issue.
Does anyone have a more elegant solution to this, or at least one that doesn’t cause a memory leak?
There is an example on cancelling tween animations right in the documentation:
var tween
func animate():
if tween:
tween.kill() # Abort the previous animation.
tween = create_tween()
My advice is this: Don’t bother with await.Do a callback instead. When the fade-in animation finishes, call a designated function. If the animation is interrupted (by the user trying to close the window before it fully finishes the appear animation), just kill the currently running tween, create a new one with a fade out animation and you are good to go!
Unfortunately, my game is incredibly menu-heavy and awaits are used countless times, and splitting up all the code after awaits in my game into multiple functions may potentially take weeks of refactoring and be much messier and harder to navigate (bad coding decisions made in the past, I understand).
Would it not be viable to keep the awaits, but try the kill() + create_tween() method? I assume the finished signal would properly fire in that case.
Nevermind everything, try cusom_step instead of killing
bool custom_step(delta: float)
Processes the Tween by the given delta value, in seconds. This is mostly useful for manual control when the Tween is paused. It can also be used to end the Tween animation immediately, by setting delta longer than the whole duration of the Tween animation.
Returns true if the Tween still has Tweeners that haven’t finished.
If a crazy high number produces crazy results you could condition a while loop with it for smaller steps