The thing is, you’re looking completely besides the point.
There are many more differences between Tween+ and TweenService, that makes Tween+ significantly better. I’d recommend reading the post.
I cannot see them either. I am on Safari.
It might be your browser not supporting AV1.
The previous issue was just that the videos were private, which is now fixed and most users are able to see them.
Any performance changes? What about replication and server handling?
Creation is much faster, but unfortunately starting playback of tweens is slower because of all of the additional features it provides.
I haven’t benchmarked CPU usage when tweening, but I can assure you that it has been optimized.
Feel free to benchmark yourself, and don’t forget to share it if you do so!
Also, the UpdateEvent
feature allows for significant performance improvements in certain scenarios. Of course TweenService does not have such a feature.
I thought about this, but this module’s purpose might not quite be that.
I want it to be usable for anybody and in any environment — it’s a replacement for TweenService.
Okay, actually I was making a similar system for animations from keyframeSequence, so I know a little bit about this topic.
Personally, I love it when people write me a lot of constructive criticism. so now I’m going to ruthlessly evaluate your code
- Well, reading your code, I still involuntarily think that there are advantages here too, so let’s write down why your code is not bad:
The documentation is right in the code before the functions, so we see hints, not bad.
Typing is definitely very good, but with the caveats that it was worth putting them in a separate module. They were made purely for “beauty” (hints), although it was possible to work hard and do it in --!strict mode. Yes, it’s difficult for not the most experienced, but still
Also, I note that the code is well organized. Although I just poke my finger into any part of the code and immediately see how to improve readability, and so on, it’s still a difficult job, so I forgive
using your own SignalPlus is good! Judging by the code, they are faster than BindableEvent.
- What I’m not sure about
UpdateEvent: Providing a choice between PostSimulation, prestimulation, and PreRender for UpdateEvent gives flexibility, but it can also lead to problems. I’m not sure if it’s worth giving this choice, or if it’s better to limit yourself to one, the most appropriate option.
table.freeze also seems to be meaningless in your code. No one in an adequate state will change a table from another code. Well, I’m not at liberty to say whether it’s bad or not.
The native directive looks meaningless in untyped code. If the code had been typed correctly, --!strict would have been enabled, which would have added 20-30% of the code speed, but here the typing was done so that there would be no eye gouging, so this is not only pointless, but even a small anti-pattern is possible.
minuses:
The main problem: Why? The most important question that arises when viewing this code is: why create your own TweenService system? TweenService is an optimized, reliable, and supported Roblox component that provides a wide range of animation features. If there are no very good reasons to create your own system, then it is better to use TweenService. I mean, unlike your code, it’s much more type-safe, probably more convenient, and so on. Just create a wrapper for it that adds functionality.
The propertyExists function uses pcall, which is quite expensive. It is better to use smg like “offline API” and check OflflineAPI[object][property] == nil
(or API[object][property]
if u can)
The code is quite complex to understand and debug.
I didn’t notice any logic processing when we try to run two twins of the same property for an object. it would be nice to have a weigh system
I also didn’t notice the logic processing when the instance was destroyed. It will most likely give an error, but I think many people would like to be warned so that their myservergamainbestsuperpuper
does not turn off due to a destroyed DataStorePartAttributetagImACollectionService
(just joking)
also, the structure is not very good in my opinion.
In the current implementation, each tween creates its own separate connection to the RunService.Prestimulation (or another selected UpdateEvent). This can lead to significant overhead costs, especially with a large number of simultaneously running twins.
Ideally, we strive to ensure that all active tweens are handled within a single connection to the RunService.PreSimulation. This will significantly reduce the load on the CPU and improve performance.
Consider using a centralized scheduler that will iterate through all active tines and update their values within a single RunService cycle.PreSimulation. This will require a more complex architecture, but will eventually lead to more efficient operation.
instanceTweens
using Instance as a key is a problem. Use Weak Tables.
Or use a unique ID, although I find it pointless.
looked into easing WTHELL MAN THERE ARE SO MANY REPETITIVE LINES OF CODE! “Magic numbers” are bad
(Im used google translator, Im sorry if my text is “unreadable”)
AW:
and I would also say that instead of string … string, you should definitely do `{string1} {string2}(``), except for the moments with tables.
There’s a lot of duplicate code here
To configure it, consider the builder pattern, for example, in roblox it is a separate “TweenInfo” object
How exactly is it superior to existing solutions like:
I appreciate that you took your time to thoroughly review my resource.
But you missed a lot.
I’ll reply to your points in order, one by one:
-
The
UpdateEvent
can actually used for optimization, which is why I added it. See EgoMoose’s tweet about it. -
table.freeze
is not quite meaningless here. I know it’s not used often, but your argument against it is awful, because what you’re basically saying is that you can trust the user with anything — so you’re saying that you don’t have to verify the passed arguments, because you’re sure that the user did it correct — instead, ensure full robustness. -
--!strict
is not for optimization. You’re not magically going to get better performance using strict typing. -
There have been many complaints about TweenService performance, and it’s also lacking many features that custom alternatives like Tween+ provides. TweenService is also not more type-safe than Tween+. A wrapper is a super unoptimized method of doing it, and you can barely add anything to the functionallity.
-
pcall
is not expensive. It’s only used in the tween creation, which is way faster than what TweenService does. Also, using an offline API will not be up-to-date, which is a huge concern. -
From reading other people’s code, I clearly see that I have my own style. But it’s not new that it’s hard to read other people’s code. I’d say my code is very readable and easy to debug.
-
Combining all tween logic into one loop is insanely tough if not impossible, and if it’s possible, it would absolutely demolish readability. This is due to how much the tween logic can vary from tween to tween — some tweens repeat, some reverse, some delay, and some don’t even run at full FPS. Additionally, single-threaded processing might be slower and more memory-inefficient than multi-threaded.
-
I see that Tween+ lacks instance destroy-handling, and I’ll be adding it in the next version, thanks!
-
The tween functions aren not very readable yes; many constants are hard-coded. But it’s not meant to be super readable, because there’s not much to improve.
-
The way people use string concatenation is very different. Some use
..
and others make use of{}
. I prefer..
and will not be changing it. It’s personal preference. -
A seperate TweenInfo object only complicates things. It provides absolutely no benefit. A table with autocompletion is way more intuitive.
And please read the post, because Tween+ has so many improvements over TweenService. It’s absolutely the opposite of meaningless and useless.
The top of the post lists features that Tween+ offers but TweenService doesn’t.
Compare it to what your linked “CustomTweenService” provides, and you should see many reasons as for why Tween+ is superior.
You can also check out some of my other replies to users on this topic, or see showcases and read the rest of the post for more information on the features and the syntax.
I want to hear a constructive reason why, not just a “look yourself”. I created my module mainly to add extra abilities like editable amplitude and period of certain tweens as well as OutIn style. What is the superiority of your module over my solution besides that? That’s what I am asking. Sorry if you misunderstood me initially.
- Many more data types.
- Full typing.
- Intuitive customization (TweenInfo) table without constructor.
- Insanely optimized signals (my Signal+ module).
- Many more tween signals to listen to.
-
Reset
method for tweens. - FPS limit control.
- Attributes support.
I just ran tests and realized that you are right, strict typing does not give performance. It’s strange why I thought that…
Someone else’s code is really hard to read however, I’ll be honest, it doesn’t matter, but I just opened your code and I see that you literally write the signal CLASS with a small letter, this is just an example.
about one single prestimulation: Well, you can’t argue with that, about half a year ago I also tried to implement a similar thing. (Spoiler alert, I didn’t succeed) however, it would clearly be a very good practice.
About the third one, okay. but still, I note that you are the first person I have met in this entire forum who explicitly said that he prefers concatenation instead of string interpolation. I don’t mind, the main thing is that it’s not string.format)
I read the post again and…
And that begs the question, will you do an automatic client twin when requesting from the server? This is literally the first thing that should come to mind when creating such systems
tween from TweenService start are 60+ times faster than 1 your tween
Why? Because TweenService is written in C++, I suppose
did you mention that the table has auto-completion? The question immediately arises: why make a dictionary-like table if you can just write the type? well. Okay, this can be explained by the existence of those. who is bad at programming.
also, I like the opportunity to tweak attributes, although I still haven’t figured out how it happens. It would be cool if you added the ability to write your functions in style, like a “Cool feature”, like function(a,b,t) smthing cool here end
I know. that it can be done manually in your code in 5 minutes, but having an interface for it would be cool.
Personal preference.
I still see it as very unlikely to be beneficial, but I’ll give it a try for you.
While TweenService is written in C++, which is a big advantage, the speed difference is also due to Tween+ having many more features, which takes up a lot of processing to account for every :Play()
.
Not quite sure what you mean here. It’s hard to understand your language.
What. If you want to work further on the module, then do it.
Personal preferences.
You understand, this is literally the same as writing local PART_OBJECT = workspace.part, this is a common practice, classes are PascalCase, camelCase objects, constants are UPPER_SNAKE_CASE
I still see it as very unlikely to be beneficial, but I’ll give it a try for you.
I’m not sure if you should work on something that you don’t think is useful for the sake of another person’s request. However, it is more likely that it will really benefit.
While TweenService is written in C++, which is a big advantage, the speed difference is also due to Tween+ having many more features, which takes up a lot of processing to account for every :Play().
and that’s exactly the conclusion you should get. Creating such a module should primarily complement
it with its functionality, but not replace
it, so yes, this is what makes your module usable, but still, it is not a substitute for TweenService.
Not quite sure what you mean here. It’s hard to understand your language.
Yes, Im sorry, the translator is bad when it comes to terms.
One of the biggest selling points for this module is the fact it’s “optimized”, although I didn’t see a whole lot of detail explaining how or what is exactly being optimized
Version 1.2.0
Changes & fixes:
- Completely new tweening system that avoids coroutines completely, improving performance immensely.
- Changed the pause handling logic, also removing
Playing
value, as now it uses thePaused
value to check for the playback state. - Updated Signal+ to v2.7.0.
- Changed error message ‘level’ to 2 for easier debugging.
- Internal tween type for type checking inside the module itself.
- Moved hardcoded default repeat count to a variable.
- Moved if statements for returns in easing functions into one return statement.
- Switched class names to PascalCase.
- Comment changes and additions.
- Spacing and order changes.
Version 1.3.0
Changes & fixes:
- Now handles instance destroy.
- Added early exit in tween updation functions.
- Removed unnecessary operations in
Destroy
method. - Removed
updateEvents
table, now uses previousactiveTweens
as that. - Added signals to internal type.
- Applied internal type more places internally.
- Minor comment changes and additions.
let him write his code how he wants brotha
NOT_A_PART_CONSTANT_OR_SIGNALCLASS_OR_SOMTIMES_NIL: Signal|number|boolean|nil= not nil
It doesn’t help to exaggerate. Also that just proves how ugly UPPER_SNAKE_CASE is, so that’s why I don’t use it.