KyryloKuzyk / PrimeTween

High-performance, allocation-free tween library for Unity. Create animations, delays, and sequences in one line of code.
https://assetstore.unity.com/packages/slug/252960
Other
982 stars 39 forks source link

Overshoot / Amplitude for Back / Elastic Ease? #11

Closed iMobCoding closed 1 year ago

iMobCoding commented 1 year ago

Is there some obvious way, that I am missing, to get an overshoot for Back Eases? I know I can use custom curves, but that's an overkill for a simple thing I use all the time. I often use something like OutBack with overshoot to amplify the Back effect in DOTween...

Similar question goes for amplitude in Elastic Eases

KyryloKuzyk commented 1 year ago

Because the overshoot (or amplitude) concept doesn't apply to all Ease types, I decided to implement this feature slightly differently. There is currently an experimental Tween.PositionOutBounce() method that can be used to customize the default Ease.OutBounce and Ease.OutBack:

// Custom Ease.OutBack with an overshoot of 2m (negative -2f amplitude means 'overshoot') 
Tween.PositionOutBounce(transform, endValue, duration, amplitude: -2f, numBounces: 1);

// Custom Ease.OutBounce with bounce amplitude of 1.5m and a medium stiffness
Tween.PositionOutBounce(transform, endValue, duration, amplitude: 1.5f, numBounces: 3, stiffness: 0.5f);

This API allows to specify the exact amplitude in meters, which means that regardless of the animation distance, the bounce amplitude will stay the same.
Also, you can pass the stiffness parameter to tweak the 'springiness' of the animation.

This is currently an experimental feature that may change before the official release and it requires the PRIME_TWEEN_EXPERIMENTAL in the ProjectSettings/Player/Script Compilation. If you have a better name for Tween.PositionOutBounce(), I'm open to suggestions.

I would love to hear your feedback regarding this approach. If it's fine, I can implement custom elastic eases in a similar manner.

iMobCoding commented 1 year ago

Yes I see your intention but it's for the position only. Where I usually use overshoot is scale, to amplify the size change when starting and ending scales are pretty close. And someone may use it for rotation or whatever. So creating additional methods for all those usecases seems inappropriate. And btw, are you sure that PositionOutBounce with negative amplitude and numBounces of 1 produces the same curve as OutBack? I tried with various amplitudes and the curves didn't look the same. Finally I checked and saw that you use InSine and OutSine in CustomOutBounce() but can that produce the same results as OutBack?

I know overshoot/amplitude doesn't apply to all eases, but with good documentation it may be more appropriate to have those parameters instead of more methods. That's how DOTween handled it also. Maybe even name it like backEaseOvershoot, or elasticEaseAmplitude to more emphasise its usecase. Not to mention I maybe want to use endDelay, cycles or whatever with that OutBounce method, which is currently impossible if you don't make those overloads manually.

KyryloKuzyk commented 1 year ago

Fair criticism, thank you! This is the reason why this API is currently experimental.

Yes, the curves are different because the Tween.PositionOutBounce() method was designed for a custom bounce with a fixed amplitude. It can 'resemble' the Ease.OutBack, but I agree that the animation feels totally different.

I believe I have a vision for how this feature can be implemented properly while keeping the API consistent. Will share my vision here soon.

KyryloKuzyk commented 1 year ago

In version 1.0.11 I added a new Easing struct that serves as a unified wrapper for interpolations.

I took the naming convention from Android system, and will add other easing methods in future releases. The new Easing struct can be used to parametrize the amplitude of OutBack and OutElastic eases, like this (requires the PRIME_TWEEN_EXPERIMENTAL define):

Tween.PositionY(transform, endValue, duration, Easing.Overshoot(strength));
Tween.PositionY(transform, endValue, duration, Easing.Elastic(strength, period));

Also, the Easing struct can be used as a wrapper for the Ease enum or AnimationCurve:

Easing easing;
easing = Easing.Standard(Ease.InOutSine);
easing = Easing.Curve(animationCurve);

It's still possible to use the Ease enum for creating tweens. Static Tween methods now accept the Easing struct instead of AnimationCurve, but from the user's perspective nothing has changed: it's still possible to use the AnimationCurve where the Easing struct is needed.

@iMobCoding I would appreciate your feedback regarding this new feature.

iMobCoding commented 1 year ago

Checked and it works great now :)

There is still a difference between DOTween and PrimeTween regarding the overshoot. DOTween uses absolute value for the overshoot while you are multiplying the overshoot with the constant 1.7 (backEaseConst). So while I tested I used overshoot of 5f for DOTween and had to use around 3f for the PrimeTween to get the same effect. Of course, that's a design choice and maybe yours have more logic to it, but if you want to make it easier for users switching from DOTween to Prime, maybe you want the same behavior...

Also the default Elastic curve doesn't look the same between DO and Prime. I tried with a few strength/period values but couldn't achieve the same look. Didn't dive too deep into this so I don't know who implemented it the right way, but just saying it doesn't look the same :)

Nevertheless, this is a great update, along with the OnUpdate addon 👍

Edit: Btw, maybe you should have a changelog here on the repo too. Right now I have to go to Asset Store to check what's new instead of having everything in one place. And also the documentation here doesn't seem to follow the changelog. I think you should update the readme here as soon as something leaves the experimental phase (maybe even have the experimental stuff mentioned here would be nice)

And thanks once more for the great plugin 😃

KyryloKuzyk commented 1 year ago

@iMobCoding Thank you for the feedback!

DOTween uses absolute value for the overshoot while you are multiplying the overshoot with the constant 1.7 (backEaseConst)

The original Robert Penner's OutBack implementation and the most popular JS tween libraries (gsap, tween.js) all have the 1.70158f multiplier. So I'm still not sure what implementation to take. Yes, DOTween is Unity's industry standard, but all non-Unity world uses the multiplier.

Also the default Elastic curve doesn't look the same between DO and Prime. I tried with a few strength/period values but couldn't achieve the same look. Didn't dive too deep into this so I don't know who implemented it the right way, but just saying it doesn't look the same :)

Because DOTween normalizes the period depending on the duration. I also did this in version 1.0.12, it seems reasonable.

Btw, maybe you should have a changelog here on the repo too.

Good point, will do that!

And also the documentation here doesn't seem to follow the changelog.

Just updated the docs with the advanced section, thank you!