-
-
Notifications
You must be signed in to change notification settings - Fork 97
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rework the Tween system to allow more flexibility and readability #3515
Comments
To me, the current API, with the current names, is relatively intuitive. The factory methods like If people struggle to understand or use it overall, then why not change the way it works. But that should be the starting condition. I personally haven't had trouble trying the new system for concrete tween animations. If others struggle with the new system and feel the proposed one's more intuitive, I'd just like to recommend naming changes. To me, "parallel()" doesn't suggest I'm opening a group that I have to close. I prefer explicit names like: create_parallel_group() or make_parallel_group() instead of parallel() and close_group() instead of end(). That way, the intended usage is clearer. I'd also personally rather use a data structure to represent this kind of group/layer structure rather than factory methods. It would better fit the proposed uses (a bit like how flutter and other web frameworks let you define structures or animations). Although nowhere else in GDScript you have something like this so I don't think it fits well into Godot's API. Anyway, the most important aspect for me is to first see if more people have had issues working with the current API in practice. |
Another option: var tween = create_tween()
tween.tween_property(...).play() # 1
tween.parallel(
tween.tween_property(...), # 2
tween.tween_property(...) # 3
).play()
tween.parallel(
tween.tween_property(...), # 4
tween.chain(
tween.tween_property(...), # 5
tween.tween_property(...) # 6
)
).play() Or evenvar tween = create_tween()
tween.chain(
tween.tween_property(...), # 1
tween.parallel(
tween.tween_property(...), # 2
tween.tween_property(...) # 3
),
tween.parallel(
tween.tween_property(...), # 4
tween.chain(
tween.tween_property(...), # 5
tween.tween_property(...) # 6
)
)
).play() |
This is actually how it works now. I think it might be possible to implement what you suggest without any changes to the API. We could add a GroupTweener, that would act as a "sub-Tween" and allow more advanced mixing. Although with this we would have 2 ways of sequencing/paralleling animations and the system would be more complex/confusing for users. Another option is adding what I thought about initially - CustomTweener, a Tweener that exposes |
If this #623, #3490 implemented we can do something like this var tween1 = create_tween()
tween1.tween_property(...) # 1
with tween1.parallel():
tween_property(...) # 2
tween_property(...) # 3
tween1.tween_property(...) # 4
with tween1.parallel():
await tween_property(...).finished # 5
var tween2 = create_tween()
tween2.tween_property(...) # 6 this is more readable, I think |
The methods naming is surely subject to change, I just borrowed a few names that were already in use in the previous implementation.
I'm not familiar with how Flutter works in this regard but factory methods like
Exactly, having two ways to declare tweens is not ideal.
To me, that is just another complementary tool that doesn't supersede this proposal. |
I hope something like this gets implemented. I was about to open a similar proposal until I found this. In my opinion, Tweens should be entirely composed of Chain and Parallel "containers" with Tweeners in them. Entirely remove Here is a syntax inspired, of all things, by BoxContainers and how VBox and HBox containers are nested in them:
A real example of transition between levels in my game, just to show it in practice:
becomes
|
@MewPurPur This requires adding a special GDScript syntax just for Tweens, so unlikely it will get added. |
True, I posted because all of the syntax proposed here has also been special for tweens and/xor somewhat inconsistent with GDScript, and my syntax idea was the most compact/clear by far IMO. Tbh if tweens are deemed a really important class, a unique syntax shouldn't be off the table (but still undesirable) |
I found this thread because I really enjoy using tweens in my game code, both when I was working with Unity/C# and DOTween, and now with Godot. I think adding the ability to nest tweens within each other would go a long way towards allowing for more complex tween workflows. # Holds the sequence of 5-then-6
var subtween_5_6 = create_tween()
subtween_5_6.tween_property(...) # 5
subtween_5_6.tween_property(...) # 6
# Holds the sub-sequence of 4 at the same time as 5-then-6
var subtween_4_5_6 = create_tween()
subtween_4_5_6.tween_property(...) # 4
subtween_4_5_6.parallel().tween_subtween(subtween_5_6) # 5-then-6
# Overall tween
var tween = create_tween()
tween.tween_property(...) # 1
tween.tween_property(...) # 2
tween.parallel().tween_property(...) # 3 at the same time as 2
tween.tween_subtween(subtween_4_5_6) # 4 and 5-then-6 When a Tween is passed to This sort of behavior would also make it a little comfier to dynamically build tween sequences from various objects. Say you have a bunch of sprites you want to scale up then down in sequence. You could define a function on the sprite's script like so: func bounce_tween() -> Tween:
var tw = create_tween()
tw.tween_property(self, "scale", Vector2.ONE * 2, 1.0)
tw.tween_property(self, "scale", Vector2.ONE, 1.0)
return tw Then, you could have them animate in sequence: func animate_all_sprites():
var tween = create_tween()
for spr in sprites:
tween.tween_subtween(spr.bounce_tween()) Note I know this is already possible by passing a Tween object to the function, like so: func bounce_tween(tw: Tween):
tw.tween_property(self, "scale", Vector2.ONE * 2, 1.0)
tw.tween_property(self, "scale", Vector2.ONE, 1.0) But then, if you just want to bounce one sprite on its own, you have to pass it an empty Tween object, which feels a little icky to me: one_sprite.bounce_tween(create_tween()) And the subtween function would help with cleaner, clearer setup of sequences in other ways, so I still think it'd be a good addition. |
Describe the project you are working on
Not relevant.
Describe the problem or limitation you are having in your project
The current version of the Tween system in 4.0 is surely an improvement over the 3.x one.
But in my opinion it has a few pitfalls that could be fixed in time with the final release and would bring improved usability for intermediate to advanced users, still keeping it simple for basic stuff.
Here's an example for a tween configuration:
The current implementation provides several approaches to get this result.
Await approach:
Callable approach:
Mix:
There is a recurring problem with each approach: declaring parallel tweeners is often confusing, error prone or requires the use of several language features that could be avoided.
Describe the feature / enhancement and how it helps to overcome the problem or limitation
A more flexible way of declaring complex tweens is preferable in my opinion.
Tween objects would be containers of Tweeners.
Tweeners can be simple PropertyTweeners, MethodTweeners, etc. or group of tweeners: SequenceTweener, ParallelTweener.
Tweens and groups of tweeners can create and append other tweeners to themselves.
When they do, the new tweener is returned, and can be used to further create and append nested tweeners.
If a non-group tweener tries to generate a new tweener, the newly created tweener is requested to be added to the parent tweener until a tweener group is found.
Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams
This is the approach this proposal proposes, here illustrated in length:
The one above is the lengthy and verbose approach that provides the highest flexibility.
E.g. groups of tweeners could be passed around and configured independently from the other steps of the tween.
For simpler or more strainghforward tween configurations, here's what the proposed API would allow:
This version is much more readable and doesn't involve using other GDScript features in a creative way.
If this enhancement will not be used often, can it be worked around with a few lines of script?
Maybe a GDScript wrapper around the current implementation is possible but it's not very convenient.
Is there a reason why this should be core and not an add-on in the asset library?
Tweens should provide flexibility out of the box, it would be a shame to have almost all the components needed to bring their usability to the next level, just to lack a few of them.
The text was updated successfully, but these errors were encountered: