-
-
Notifications
You must be signed in to change notification settings - Fork 21.5k
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
Making Tweens more straightforward and useful #26529
Comments
One aspect of this is that the scene tree is not a singleton AFAIK, so contrary to DOTween you'd need to pass the tree somehow as argument of the tween statement (while in Unity, new objects are directly created in the scene), as long as tweens are nodes. Then DOTween can build on top of this and expose its API as static functions, also performing pooling so allocations are minimized if you run hundreds of tweens (yes we keep saying Godot doesnt need pooling, but I still don't believe that constructing nodes has no cost). Note: Unity does have equivalents of AnimationPlayer. Also, different start/end values is possible by changing keyframes at runtime, I did that in my game. It's just a bit unfriendly. |
There must be a reference to tree root somewhere. And if there isn't, well, you are supposed to pass the object as one of arguments. Calling
If you mean the timeline thing, it's nowhere as good as Godot's.
Yeah, my proposal is supposed to eliminate the unfriendly part. |
I'm talking about I wonder if there is a way to sketch an API like this using static GDScript wrapper functions? Although the concept of sequences would have to be introduced. |
I'm thinking about doing this and I even have idea how, including sequences. Also, DOTween is open-source, so we could look how they did it too. |
Wow, that was easy: Here's the effect: And here is the code:
Tweens are created and destroyed automatically, there's no need for any singleton. Everything is handled by single class in one script. I used get/set_meta to store Tweener objects, so they are not freed. The only problems are that you need to pass SceneTree to sequence somehow (that's why Tweening.senquence requires a Node argument) and that Godot supports method chaining only with awkward brackets at the beginning of the line. But well, still better than this:
which I believe would be the current equivalent. It's easy to extend it to support intervals in sequence (alternative to delays), looping, callbacks etc. The point of this issue is that this functionality is how Tweens should work, as they are close to useless without such wrappers due to unwieldiness. On the other hand, the 5-line code I used in the example could be arguably easier to write than using AnimationPlayer, so it's nice for quick animations. |
in the "cocos2d-x" is also a tree. But there the tweens (Actions) work fine. MoveTo, MoveBy, ... (Interval Action) |
I agree that
My proposal to address this issue: Add a
Enums used in the constructors are defined as follows:
Constructors correspond to the methods that are currently present in
In addition to these constructors, there will be functions for setting the additional tweening parameters. These will be:
Sequence timing is a new proposed feature. It will be used for controlling behaviour of action sequences. As for the
The second overload will be used for already mentioned action sequences. It will simply accept array of Translating your example to proposed API:
In my opinion, this is cleaner, more typical GDScript syntax. Let me know what you think of this. |
I don't like how you create a variable for each TweenAction and then pass them in an array. They are meant to be played in sequence. What if you have a sequence of 30 actions? Create 30 variables? I guess you could just make an array at the beginning and append each action as you create them. But it's just... weird to do. And if you decide to make e.g. TweenActions store previous action somewhere and then start only the first one, you either end up with double amount of code or necessity to create a variable for action (again, unfeasible for long chains). Yes, my code is taken straight from Unity and only translated to work with GDScript. But the idea is to make the process as simple as possible, with the Tween system doing automatically as much as possible. I'm just against any unnecessary verbosity of the code, even if it's against some conventions >.> EDIT: |
If you dislike the creating variables part then another option would be to create something like Yes, I get that you just tried to get the idea across. And I agree that unnecessary verbosity is just that... Unnecessary. However, I disagree that shorter syntax should be preferred at the expense of readability or maintainability. Either way, I don't think there's any point in arguing over syntax if we don't know whether reworking |
I personally disagree, I don't think the Tween workflow is really something that needs changing. That said, I can sort of(?) see an argument for making them more straightforward. As a suggestion, perhaps we can take these four lines: var tween = Tween.new()
tween.interpolate_property(node, property, initial_value, final_value, duration, transition_type, ease_type, delay)
add_child(tween)
tween.start() and simplify them down to something like this: tween(node, property, initial_value, final_value, duration, transition_type, ease_type, delay)
# Side note: transition_type and ease_type should really have defaults! This would, in theory, perform all the same steps as the four lines of code above, but with a single function call. This function would probably live either in |
This only seems to take care of interpolating property, though. So, my suggestion seeks to address two points:
That said, I understand that reworking
|
I randomly thought about Tweens and looking at the example code again, do we even need Tweens to be nodes? There's no editor plugin related to Tweens and the few inspector properties could be as well controlled by code. Also, all the behavior is controlled by code anyways. Maybe we could rewrite the Tweens into independent objects similar to SceneTreeTimers? |
it can be paused when scene is paused because it is a node inside tree. |
Setting the defaults for |
@LikeLakers2 I've kinda managed to implement this as a GDScript method in https://github.com/Xrayez/godot/commit/341787415057bed912c85dc26becec685dbc4bf3 but I've stumbled upon node workarounds there having to make deferred calls.
You can access the scene tree via C++ as Tween *tween = memnew(Tween);
SceneTree::get_singleton()->get_root()->call_deferred("add_child", tween);
tween->interpolate_property(obj, property, initial_val, final_val, duration, trans_type, ease_type, delay);
tween->call_deferred("start"); It looks like this when used via GDScript: # Fade away Godot sprite, free upon fading completely
animate($Godot, "modulate:a", null, 0.0, 5.0).connect("tween_all_completed", $Godot, "queue_free")
It seems like it's the current functionality, not sure if this was added recently. So these "hacks" suggest that it could rather be made closer to the scene tree indeed. I gravitate towards similar to
According to API one can achieve similar pausing functionality: So similar could be achieved for a tween I believe. The usage would look like so: var tween = get_tree().create_tween($Godot, "modulate:a", null, 0.0, 5.0)
tween.connect("finished", $Godot, "queue_free") It would also ensure that the tween is started automatically and freed upon finishing. |
I'm thinking about making a proposal for overhauling Tweens into something like I did here: godot-extended-libraries/godot-next#50 Methods from my TweenSequence could become Tween methods and instead of relying on underlying Tween, the Tween would animate on itself and you'd lose access to current methods and only use them via the new interface. Every problem from Tween being changed to Reference can be resolved. |
This sounds like a good idea, and I like your solution better, but there already is a Tween Sequencing rework Pull Request that has been put off to the next version twice already #20934 I guess a decision is needed from the leadershop on the direction of these Tween reworks. Just one suggestion - there currently isn't any way to get a list of Tweens from a Tween class. I think it would be useful to have a way to get an array like that. Especially, if we will be able to sequence them. |
Closing this in favor of godotengine/godot-proposals#514 |
Godot version:
3.1 beta10
Issue description:
Some time ago I used an Unity extension called DOTween. It was one of the best things I had come into. Compared to that, Godot's Tweens are terrible. Well, this might be also because Godot has AnimationPlayer, which Unity doesn't, but whatever. The only use for Tweens I see right now is animating properties that might have different start/end values, which AnimationPlayer doesn't support. However I never actually used Tweens and when needed I rather went with simple lerp.
To fix that, I'd like to suggest a complete overhaul of Tween workflow, to make it more like DOTween. Right now to tween something you need to do:
The DOTween equivalent would be this, somewhat translated to Godot-ish:
Or even simpler:
As for the second way, it works by somehow extending the target object to add tweening methods. I guess it's unfeasible unless there's a way to enable it per script, because otherwise every object would have tweening stuff not everyone uses.
As for the first one, that's how it should work IMO. It tweens the property from current value to target one in given time. "get_scale" and "set_scale" are getters/setters for the property. DOTween uses lambdas for that, but since we can just provide property path like in current
interpolate_property
, then maybe it's not needed.Anyways, calling this method would automatically add the Tween to scene and start it. So it's a "fire and forget" approach and that's infinitely more useful than it's right now. Also, sequences. This is code from an issue about Tween sequencing (#17543, with one change):
DOTween's way would be something like (with the getter/setter removed as I mentioned):
or
Much simpler, much more clear. It's just about adding static methods that make working with Tweens as straightforward as possible, by doing much of the work for you. It also simplifies methods by removing arguments and delegating them to other methods (it's simpler when you e.g. set a default ease and don't need to change it, so you don't repeat it all the time). It works because To() method returns Tweener and you can change its properties or append to sequence. Since managing this is done automatically, it's much more productive.
So that's it. I've seen another issue (#22513) that there's some Tween overhaul coming, so this might come as idea on how could they eventually work.
The text was updated successfully, but these errors were encountered: