Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

PrimeTween · High-Performance Animations and Sequences

Discussion in 'Assets and Asset Store' started by KyryloKuzyk, Aug 15, 2023.

  1. KyryloKuzyk

    KyryloKuzyk

    Joined:
    Nov 4, 2013
    Posts:
    1,070
    @yuliyF Quaternions don't represent the Euler angles, they represent the 'orientation' of the object. Because of this, these two rotations are actually identical
    Quaternion.Euler(0, 0, 360) == Quaternion.Euler(0, 0, 0)
    and the tween will do nothing. For the same reason, it's impossible to animate rotations beyond 180 degrees using Quaternions.

    To address this, there is the Tween.EulerAngles() method in PrimeTween that can animate the eulerAngles property. It can be used to animate loading indicator like this:
    Code (CSharp):
    1. Tween.EulerAngles(loadingIndicatorTransform, Vector3.zero, new Vector3(0, 0, 360), 1, Ease.Linear, -1);
    There are several ways to stop infinite animations. If you wish to interrupt the animation instantly, then call Stop() on it. If you want the animation to finish the current cycle, then use SetCycles(0):
    Code (CSharp):
    1. Tween tween;
    2. public void StartLoadingAnimation() {
    3.     tween = Tween.EulerAngles(loadingIndicatorTransform, Vector3.zero, new Vector3(0, 0, 360), 1, Ease.Linear, -1);
    4. }
    5. public void StopLoadingAnimationInstantly() => tween.Stop();
    6. public void StopLoadingAnimationAtTheEndOfCycle() => tween.SetCycles(0);
    Also, you can use the
    Tween.StopAll(loadingIndicatorTransform);
    method which doesn't require storing the tween struct. It has a worse performance in comparison to tween.Stop(), but it's okay to use it once in a while (not every frame).
     
    Last edited: Sep 18, 2023
    yuliyF likes this.
  2. RisingSunStudios

    RisingSunStudios

    Joined:
    May 23, 2018
    Posts:
    32
    I'm noticing performance issues where I didn't have previously with Dotween, specifically with the OnComplete callbacks. I'm fairly certain nothing else has changed in my code base that would cause it, but haven't done a deep-dive into it yet so asking here pre-emptively until I can get home and check later.

    For example, say I'm using this code to move a bullet and when it completes I calculate damage. I can have hundreds of bullets flying at the same time but not many completing the tween in the same frame.

    Code (CSharp):
    1. Tween tween = Tween.To(...)
    2. tween.OnComplete(OnComplete, false);
    Now the OnComplete function will do some calculations and trigger more tweens to display floating text. I don't suppose you know how that would compare with Dotween, or if there's a better way to do this, such that would ensure the tween is available for recycling/reuse before the OnComplete is called?

    Chances are it's my issue and not PrimeTween, but maybe using ChainCallback() would be a better pattern regardless?
     
  3. KyryloKuzyk

    KyryloKuzyk

    Joined:
    Nov 4, 2013
    Posts:
    1,070
    @RisingSunStudios Hmm, OnComplete() should not cause any issues compared to DOTween, especially if nothing has changed except the transition to PrimeTween. I would appreciate more info on this issue later when you get home.

    One thing I noticed is that the code you showed has a delegate allocation in it. However, this allocation was there before the transition to PrimeTween, so I don't think this is the cause of your performance issues. The delegate allocation can be addressed like this:
    Code (CSharp):
    1. Tween tween = Tween.Custom(...)
    2.     .OnComplete(this, target => target.OnComplete());
    Another idea that comes to mind is the amount of running tweens, you can check all of them in the PrimeTweenManager's Inspector.

    If you're already chaining several tweens to one another, then use ChainCallback(). But for a single tween with a single OnComplete() callback, your usage is perfectly fine.

    While Sequence with a ChainCallback() is slightly slower (because it starts a new tween under the hood), I would suggest using what's more readable and maintainable. Both approaches are extremely fast and should not create performance bottlenecks.

    To interrupt the tween and ignore the OnComplete() callback, just call tween.Stop(). When tween is stopped manually or completed, it will be automatically recycled. But as a user, you should never think about tween recycling/reuse, PrimeTween will take care of it automatically.
     
    Last edited: Sep 18, 2023
  4. RisingSunStudios

    RisingSunStudios

    Joined:
    May 23, 2018
    Posts:
    32
    Great, thanks for the info! I'll let you know what I find out later, probably user-error! :)
     
    KyryloKuzyk likes this.
  5. cylim_unity

    cylim_unity

    Joined:
    Aug 30, 2023
    Posts:
    1
    I have become interested in 'PrimeTween'. I would like to preview the tween system in the editor. This feature is offered in DoTween. Are you planning to add this feature?
     
  6. KyryloKuzyk

    KyryloKuzyk

    Joined:
    Nov 4, 2013
    Posts:
    1,070
    This is currently not possible in PrimeTween. I'm planning to include the 'Editor Preview' feature to the PRO version in the future.
     
  7. PandaK3NZ

    PandaK3NZ

    Joined:
    Aug 13, 2023
    Posts:
    1
    Is there a Discord server dedicated on people using PrimeTween? It would be so helpful to communicate with the experts and get a right away help. :D
     
  8. KyryloKuzyk

    KyryloKuzyk

    Joined:
    Nov 4, 2013
    Posts:
    1,070
    Version 1.0.12 is out!
    ## [1.0.12] - 2022-09-22
    ### Added
    - Experimental: add parametric Easing.Bounce(float strength) and Easing.BounceExact(float magnitude). BounceExact allows to specify the exact bounce amplitude in meters/degrees regardless of the total tween distance. This feature requires the PRIME_TWEEN_EXPERIMENTAL define.
    - Add From(fromValue) method to adapter.
    - Support parametric OutBack and OutElastic eases in the adapter.
    ### Changed
    - Easing.Elastic: normalize the oscillation period by duration; this ensures the tween has the same period regardless of duration.

    ## [1.0.11] - 2022-09-21
    ### Added
    - Tween.GlobalTimeScale(), Tween.TweenTimeScale(), and tween.timeScale are no longer experimental.
    - Add tween.OnUpdate() to execute a custom callback when the animated value is updated.
    - Experimental: add Easing.Overshoot(float strength) and Easing.Elastic(float strength, float normalizedPeriod) methods to customize Ease.OutBounce and Ease.OutElastic.
    ### Changed
    - Tween methods now accept Easing struct instead of AnimationCurve. You can continue using AnimationCurve as before because it is implicitly converted to the Easing struct.
    - Ease.OutElastic now works the same as the most popular js and C# tween libraries.
    ### Fixed
    - Add PrimeTween.Demo namespace to Demo scripts.

    The biggest addition is the parametric easing which adds the ability to customize standard eases. For example, the new
    Easing.BounceExact(float amplitude)
    can be used to achieve the same bounce amplitude with different animation distances.
    Code (CSharp):
    1. // Regardless of the current position and endValue, the bounce will have the exact amplitude of 1 meter
    2. Tween.PositionY(transform, endValue, duration, Easing.BounceExact(1));
    Parametric easing is currently an experimental feature that requires the PRIME_TWEEN_EXPERIMENTAL define. I would appreciate your feedback before promoting this feature to production.

    Another significant feature is the OnUpdate() callback that allows to execute custom code when the animated value is updated. For example:
    Code (CSharp):
    1. // Rotate the transform around the y-axis as the animation progresses
    2. Tween.PositionY(transform, endValue, duration)
    3.     .OnUpdate(target: transform, (target, tween) => target.rotation = Quaternion.Euler(0, tween.interpolationFactor * 90f, 0));
    4.  
    5. // Call the OnPositionUpdated() method on every position change
    6. Tween.PositionY(transform, endValue, duration)
    7.     .OnUpdate(target: this, (target, tween) => target.OnPositionUpdated(tween.progress));
    Also, the custom timeScale feature is no longer experimental. You can find the documentation here.

    There is currently no discord server, I will think about creating it in the future.
    As an alternative, you're welcome to join the Discussions on GitHub, I respond to all questions there. The discussions are also searchable, so other users can quickly search for what they are interested in.
     
    Last edited: Sep 24, 2023
  9. DragonCoder

    DragonCoder

    Joined:
    Jul 3, 2015
    Posts:
    1,467
    Hey,
    the asset works nicely so far!
    Using it for little over a week.

    Am running now however into this error which has no code highlights at all:
    upload_2023-9-23_20-13-59.png

    There is a chance I'm calling Tween.Color on a null object after some bigger refactoring. Is it performance reasons that the error message cannot tell which method call exactly that was?
    If so, would it be possible to have a sort of debug mode which degrades performance but gives us such information?

    This second error occurs simultaneously:
    upload_2023-9-23_20-16-27.png

    EDIT: Yes, I was effectively calling
    Tween.Color(null,...);
    due to a missing ref. Fixing this removes both issues.
    Think errorhandling for this in the editor is quite important so the static-method approach (which I otherwise like) does not lack vs extension methods.

    Version is 1.0.12
     
    Last edited: Sep 23, 2023
    KyryloKuzyk likes this.
  10. KyryloKuzyk

    KyryloKuzyk

    Joined:
    Nov 4, 2013
    Posts:
    1,070
    @DragonCoder Thank you for reporting the issue! I was able to replicate it on my side. This null ref happens when you pass the null UnityEngine.Object reference to Tween methods. I have a check for the destroyed UnityEngine.Object (or if the reference is missing in Inspector), but I somehow missed the simple null check.

    I created an issue on GitHub so it's possible to track the progress there. I hope I'll fix the bug in the next 24 hours. The current workaround is to not pass null refs to Tween methods.

    EDIT: fixed in version 1.0.13. Huge thanks for the bug report!
    Now PrimeTween will log an error that points to the exact place where the null target came from.
     
    Last edited: Sep 24, 2023
    DragonCoder likes this.
  11. wechat_os_Qy02YYfLD1dKIIddL9E1uSc_o

    wechat_os_Qy02YYfLD1dKIIddL9E1uSc_o

    Joined:
    Apr 30, 2021
    Posts:
    2
    Sorry for the interruption. What does 'enableFalloff' mean? I am a junior developer, and I came across this parameter while using Tween.ShakeLocalPosition, but I didn't quite understand what it signifies. Additionally, there's the 'asymmetryFactor' – could you please explain that as well?
     
  12. KyryloKuzyk

    KyryloKuzyk

    Joined:
    Nov 4, 2013
    Posts:
    1,070
    Here is the XML documentation for these fields:
    You can view the documentation by navigating to PrimeTween's source code (typically by pressing ctrl/cmd + mouse click). Also, it's possible to view an inlined XML documentation in your IDE by generating a project file for 'Local tarball' packages, like this.
    upload_2023-9-26_12-55-52.png
     
  13. chumomo

    chumomo

    Joined:
    Jun 30, 2017
    Posts:
    16
    Hello, great Asset! I come across a question, From() extension used in DOTween.
    The PrimeTween Doc and Demo don't have From() example.
    How to implement this functionality?
    Thks!
     
    KyryloKuzyk likes this.
  14. KyryloKuzyk

    KyryloKuzyk

    Joined:
    Nov 4, 2013
    Posts:
    1,070
    You can specify the start value by passing the 'startValue' parameter to
    Tween.
    methods. Like this:
    Code (CSharp):
    1. Tween.PositionX(transform, startValue, endValue, duration);
    Or you can use TweenSettings<T> and tweak all animation properties from the Inspector, including the startValue.

    The documentation already mentions the startValue in a few places, but maybe I should create a separate section dedicated specifically to this topic.
     
  15. Voxel-Busters

    Voxel-Busters

    Joined:
    Feb 25, 2015
    Posts:
    1,832
    @KyryloKuzyk Congrats on the release!

    Also, got to know you did .projekt game. I used it for my nephew to explain about projections (for his engineering graphics course). It was nicely done!

    Cheers,
    VB Team
     
    KyryloKuzyk likes this.
  16. NFMynster

    NFMynster

    Joined:
    Jul 1, 2013
    Posts:
    66
    Can you manually step the tweens, like DOTween's Goto?
    Edit, while migrating, I found no replacement for sequence.timeScale, am I missing something?

    I have some sequence which I need to follow the Time.timeScale, where I with DOTween did it like that.
     
    Last edited: Oct 1, 2023
    yuliyF and KyryloKuzyk like this.
  17. DragonCoder

    DragonCoder

    Joined:
    Jul 3, 2015
    Posts:
    1,467
    Great to see the other problem fixed :)

    Question:
    Is it possible to animate offsetMin and offsetMax of RectTransform? Ideally component-wise (like only X or only Y).

    Probably a rather niche usecase, but would come in handy right now for some "highlight via scaling up"-effect on an UI object with non-uniform anchors so that classic scale does not lead to the desired effect.
     
    Last edited: Oct 1, 2023
    KyryloKuzyk likes this.
  18. KyryloKuzyk

    KyryloKuzyk

    Joined:
    Nov 4, 2013
    Posts:
    1,070
    Thank you! I'm excited to know that .projekt is not only a fun game, but also a good educational tool :)
     
    Voxel-Busters likes this.
  19. KyryloKuzyk

    KyryloKuzyk

    Joined:
    Nov 4, 2013
    Posts:
    1,070
    Currently, no, but this can be added relatively easily for tweens. Because of performance considerations, it would be harder to implement for sequences, but this is still doable.
    Can you please describe your use case? Maybe I can suggest an alternative solution.
     
    Last edited: Oct 2, 2023
  20. KyryloKuzyk

    KyryloKuzyk

    Joined:
    Nov 4, 2013
    Posts:
    1,070
    I just released the sequence.timeScale feature in version 1.0.14. Could you please check it out?
    Absolutely! Just added this feature in version 1.0.14. Please tell me if it works fine for you.
     
  21. NFMynster

    NFMynster

    Joined:
    Jul 1, 2013
    Posts:
    66
    Thank you for the timeScale, will test that out. In regards to the GoTo, this can be used to manually step your tweens and sequences which can be really neat in networked multiplayer games. I use it for such purposes, essentially only have to network the elapsed float and then perfectly interpolate on the client side.

    Imagine like an elevator or similar where server authority must be the owner of the tween.
     
    Last edited: Oct 2, 2023
  22. Denis1122

    Denis1122

    Joined:
    Jan 6, 2020
    Posts:
    8
    Hi Kyrylo!
    How i can change end value over tween update?
    (Need move actor transform to moving camera, speed based motion, PositionAtSpeed())
     
    KyryloKuzyk likes this.
  23. KyryloKuzyk

    KyryloKuzyk

    Joined:
    Nov 4, 2013
    Posts:
    1,070
    Thanks for the example!
    Just have an additional question. Given that tweens and sequences in PrimeTween are non-reusable, to use the SetElapsedTime(), you'll have to re-create the tween/sequence if it's already completed (edit: or not started yet) on the client. Would that be ok? It would look something like this in the code:
    Code (CSharp):
    1. if (!sequence.isAlive) {
    2.     sequence = StartAnimationSequence();
    3. }
    4. sequence.SetElapsedTime(elapsedTime);
     
    Last edited: Oct 3, 2023
  24. KyryloKuzyk

    KyryloKuzyk

    Joined:
    Nov 4, 2013
    Posts:
    1,070
    Denis1122 likes this.
  25. NFMynster

    NFMynster

    Joined:
    Jul 1, 2013
    Posts:
    66
    Yes for sure this is all right.
    On the topic, I realized I had a lof of these statements in my code

    Code (CSharp):
    1. if (tweenExample != null)
    2. {
    3.     tweenExample.Kill();
    4. }
    5. tweenExample = newtweenblabla
    These should now be "if Tween.IsAlive, Stop()" yes?


    EDIT:
    Well ideally the client would not have the tween automatically progressed, so it shouldn't have been completed already. With DOTween, you did set the tween to "manually update" and then I ran the elapsed code myself (inside Update() or similar)
     
    Last edited: Oct 3, 2023
    KyryloKuzyk likes this.
  26. KyryloKuzyk

    KyryloKuzyk

    Joined:
    Nov 4, 2013
    Posts:
    1,070
    Yes, correct. The code can be simplified even further by removing the
    if (tween.isAlive)
    part.

    The isAlive check is not needed before calling the Stop() or Complete() because the result of calling these methods would be the same regardless of tween being alive or not:
    - If the tween isAlive, calling Stop() will interrupt it.
    - If the tween is not alive, calling Stop() will do nothing because there is nothing to interrupt.

    So you create the tween once in Awake(), pause it, and store the reference, then manipulate it, right?

    PrimeTween's doesn't fully support this usage paradigm for two reasons:
    - The resulting user's code can be drastically simplified in the majority of use cases (less code = less bugs). The DOTweenWindow.cs example is somewhat exaggerated, but it's very close to real-world usages.
    - Paused tweens still consume CPU resources and memory, so PrimeTween's API encourages users to start animations only when they are actually needed.

    So this hypothetical example that uses DOTween:
    Code (CSharp):
    1. using DG.Tweening;
    2. using UnityEngine;
    3.  
    4. public class DOTweenExample : MonoBehaviour {
    5.     Tween tween;
    6.     bool isPlaying;
    7.  
    8.     void Awake() {
    9.         tween = transform.DOMoveY(10, 1)
    10.             .Pause()
    11.             .SetAutoKill(false)
    12.             .SetUpdate(UpdateType.Manual);
    13.     }
    14.  
    15.     public void SetElapsedTimeAndPlay(float elapsedTime) {
    16.         tween.Goto(elapsedTime);
    17.         isPlaying = true;
    18.     }
    19.  
    20.     void Update() {
    21.         if (isPlaying) {
    22.             tween.ManualUpdate(Time.deltaTime, Time.unscaledDeltaTime);
    23.         }
    24.     }
    25.  
    26.     public void StopAnimation() {
    27.         isPlaying = false;
    28.     }
    29.  
    30.     void OnDestroy() {
    31.         tween.Kill();
    32.     }
    33. }

    Will look like this with PrimeTween:
    Code (CSharp):
    1. using PrimeTween;
    2. using UnityEngine;
    3.  
    4. public class PrimeTweenExample : MonoBehaviour {
    5.     Tween tween;
    6.  
    7.     public void SetElapsedTimeAndPlay(float elapsedTime) {
    8.         if (!tween.isAlive) {
    9.             // Start the tween if it's not running yet (or already completed)
    10.             tween = Tween.PositionY(transform, 10, 1);
    11.         }
    12.         tween.SetElapsedTime(elapsedTime); // this API is currently not present
    13.     }
    14.  
    15.     public void StopAnimation() {
    16.         tween.Stop();
    17.     }
    18. }
     
    Last edited: Oct 3, 2023
  27. NFMynster

    NFMynster

    Joined:
    Jul 1, 2013
    Posts:
    66
    Yes, this would solve my usecase!
    In your DOTween exampe you're using ManualUpdate() which I'm unfamiliar with - I simply used the GoTo method for my single tween.
    But yes, your suggestion seems perfectly valid and fine to me - might have been nice have to explicitly tell the tween to not autoUpdate, like DOTween's SetUpdate(UpdateType.Manual), but not a requirement for sure.
     
    KyryloKuzyk likes this.
  28. NFMynster

    NFMynster

    Joined:
    Jul 1, 2013
    Posts:
    66
    Also, seems like there's no replacement for DOCounter, which did grant a bit of guilt using, due its excessive ToString() operations.
    Any thoughts on tweening strings? - I also noticed the DOText is missing, guess I can do that with a sequence and some delays fortunately, but yeah, now you know.
     
    KyryloKuzyk likes this.
  29. DragonCoder

    DragonCoder

    Joined:
    Jul 3, 2015
    Posts:
    1,467
    You are amazing!
    Worked like a charm :)
     
    KyryloKuzyk likes this.
  30. KyryloKuzyk

    KyryloKuzyk

    Joined:
    Nov 4, 2013
    Posts:
    1,070
    There is currently no support for UnityEngine.UI.Text and TextMeshPro. I will add that in the future, including the DOText() equivalent. Although, because of UnityEngine.UI.Text is deprecated in the latest LTS Unity version, I think I'll add the support only for TextMeshPro. TextMeshPro also has a non-allocating API, which will fit nicely with PrimeTween's design.

    Implementing DOCounter() in PrimeTween is extremely easy. However, I'm not sure if it should be part of the package because every usage is different: one may like to include a fractional part, while the other may like to display the thousands separator. Here is the non-allocating equivalent to DOCounter() that uses TextMeshPro:
    Code (CSharp):
    1. public static Tween Counter([NotNull] TMP_Text text, int startValue, int endValue, float duration, Ease ease = Ease.Default) {
    2.     return Tween.Custom(text, startValue, endValue, duration, (target, val) => target.SetText("{0:0}", val), ease);
    3. }
     
    Last edited: Oct 4, 2023
    NFMynster likes this.
  31. NFMynster

    NFMynster

    Joined:
    Jul 1, 2013
    Posts:
    66
    Absolutely fantastic - I ported all my game to PrimeTween, still have a few kinks to iron out, but I'll use this also!
    Will this be included? - if not I'll copy it over manually.

    And yes, TextMeshPro support is all I care for anyways, so thank you. Waiting on a DOText replacement, and then all my usecases are 100% covered and supported by PrimeTween.
     
    Last edited: Oct 4, 2023
    KyryloKuzyk likes this.
  32. NFMynster

    NFMynster

    Joined:
    Jul 1, 2013
    Posts:
    66
    Oh and please do integrate the DOJump and DOLocalJump, I saw the snippet on first page but would be nice to have them included - they are being used! :)
     
    c-Row and KyryloKuzyk like this.
  33. Oksh

    Oksh

    Joined:
    Jan 27, 2019
    Posts:
    10
    Hi! I'm trying your amazing tool and have met some minor issue: I'm making an object fade out, so I made a scale-to-zero tween and call Destroy(gameObject) in OnComplete. But I got the warning "Tween's OnComplete callback was ignored". Is that the right way to achieve fading out? Or should I just set warnIfTargetDestroyed: false?
     
    KyryloKuzyk likes this.
  34. KyryloKuzyk

    KyryloKuzyk

    Joined:
    Nov 4, 2013
    Posts:
    1,070
    @Oksh Please check that you don't start the same tween more than once. Or that you don't have other tweens with the OnComplete() callback on the gameObject you're destroying. You can see all currently running tweens if you select the PrimeTweenManager object in a scene.
    If you have multiple tweens that have
    .OnComplete(() => Destroy(gameObject))
    , then yes, setting
    warnIfTargetDestroyed: false
    will remove the warning. In this case, if the object has been already destroyed, then it's safe to ignore all subsequent Destroy() calls. Please see this blog post for more details on how to deal with the OnComplete() callback when the tween's target is destroyed: Is it safe to destroy an object with a running tween on it?
     
    yuliyF and Oksh like this.
  35. wechat_os_Qy02YYfLD1dKIIddL9E1uSc_o

    wechat_os_Qy02YYfLD1dKIIddL9E1uSc_o

    Joined:
    Apr 30, 2021
    Posts:
    2
    Thank you, bro! I've replaced all the DoTween in my project with your PrimeTween because I find PrimeTween very useful.
    Now, I have encountered a feature I'd like to have, which is the ability to set the UpdateType of a Tween. In my project, I want to achieve an effect where a Tween can calculate the final velocity of the Rigidbody at the end of the Update, as my Update function involves complex calculations for rb.velocity. Here's an example:

    floatTween = Tween.Custom(v_tweenSetting, value => rb.velocity *= value);

    I want it to work like this:
    floatTween = DOVirtual.Float(velocityScaleStart, velocityScaleEnd, floatTime, value => rb.velocity *= value).SetUpdate(UpdateType.Late)
     
    KyryloKuzyk likes this.
  36. KyryloKuzyk

    KyryloKuzyk

    Joined:
    Nov 4, 2013
    Posts:
    1,070
    I'm glad to hear that!
    As you've pointed out, there is currently no support for the FixedUpdate/LateUpdate in PrimeTween. I'm currently considering the use cases for this feature, but I can't find a good example that can't be achieved in an alternative way.
    For example, let's assume you have a code like this:
    Code (CSharp):
    1. using DG.Tweening;
    2. using UnityEngine;
    3.  
    4. public class Example : MonoBehaviour {
    5.     [SerializeField] Rigidbody rb;
    6.     [SerializeField] float velocityScaleStart;
    7.     [SerializeField] float velocityScaleEnd;
    8.     [SerializeField] float floatTime;
    9.     Tween floatTween;
    10.  
    11.     void Update() {
    12.         Vector3 velocity = /* calculate velocity */ default;
    13.         rb.velocity = velocity;
    14.     }
    15.  
    16.     public void AnimateVelocity() {
    17.         floatTween = DOVirtual.Float(velocityScaleStart, velocityScaleEnd, floatTime, value => rb.velocity *= value)
    18.             .SetUpdate(UpdateType.Late);
    19.     }
    20.  
    21.     void OnDestroy() {
    22.         floatTween.Kill();
    23.     }
    24. }
    The above code can be rewritten to PrimeTween the following way. In my opinion, this approach even improves the readability because all the code that calculates the velocity is located in one place, so you can reason better about the order of execution:
    Code (CSharp):
    1. using PrimeTween;
    2. using UnityEngine;
    3.  
    4. public class PrimeTweenExample : MonoBehaviour {
    5.     [SerializeField] Rigidbody rb;
    6.     [SerializeField] TweenSettings<float> v_tweenSetting;
    7.     float velocityMultiplier = 1f;
    8.  
    9.     void Update() {
    10.         Vector3 velocity = /* calculate velocity */ default;
    11.         rb.velocity = velocity * velocityMultiplier;
    12.     }
    13.  
    14.     public void AnimateVelocity() {
    15.         Tween.Custom(this, v_tweenSetting, (target, val) => target.velocityMultiplier = val);
    16.     }
    17. }
    I may add the LateUpdate feature in future releases, I just want to be sure it adds value for users and improves the resulting users' code quality.
     
    Last edited: Oct 8, 2023
  37. Landcaster

    Landcaster

    Joined:
    Nov 11, 2015
    Posts:
    12
    I have a player who collects coins. When he approaches a coin it jumps up and flies at the player. But the problem is that when the player is in motion the coin flies to the place where the player is no longer there. How can this be solved?
     
  38. KyryloKuzyk

    KyryloKuzyk

    Joined:
    Nov 4, 2013
    Posts:
    1,070
    It's hard to give advice that will cover any use case, but the possible solution to your problem may look like this.
    Code (CSharp):
    1. using PrimeTween;
    2. using UnityEngine;
    3.  
    4. public class Coin : MonoBehaviour {
    5.     [SerializeField] Transform player;
    6.     Vector3 jumpPos;
    7.  
    8.     public void Animate() {
    9.         const float jumpHeight = 3f;
    10.         const float duration = 0.5f;
    11.         jumpPos = transform.position + Vector3.up * jumpHeight;
    12.         Tween.Position(transform, jumpPos, duration)
    13.             .Chain(Tween.Custom(this, 0, 1, duration, (target, val) => target.FollowPlayer(val)));
    14.     }
    15.  
    16.     void FollowPlayer(float lerpFactor) {
    17.         transform.position = Vector3.LerpUnclamped(jumpPos, player.position, lerpFactor);
    18.     }
    19. }
     
    Landcaster and DragonCoder like this.
  39. c-Row

    c-Row

    Joined:
    Nov 10, 2009
    Posts:
    827
    Seconded. :D I have been using DOTween but decided to check PrimeTween as I need to do a lot of tweening animations in my current game, and it's so much easier to work with without having to consult the manual all the time.
     
    KyryloKuzyk and NFMynster like this.
  40. NFMynster

    NFMynster

    Joined:
    Jul 1, 2013
    Posts:
    66
    Oh hmm, did you test your DOJump replacement @KyryloKuzyk ?
    In my case, triple tested this with correct positions, and it seems it's jumping up way above the target position - and it doesn't return to the target position at all.

    Edit: Oh shoot, this is because I'm using it for a 2D game, I see it uses the Z axis in your code. - Hmm upon further inspection, the Y position is always 0 when the jump is done
     
    Last edited: Oct 13, 2023
    KyryloKuzyk and NBatu like this.
  41. KyryloKuzyk

    KyryloKuzyk

    Joined:
    Nov 4, 2013
    Posts:
    1,070
    @NFMynster Oh yes, somehow I missed to add the iniPosY in this line:
    var to = (i + 1) * deltaJump;
    . The correct Jump() method should look like this:
    Code (CSharp):
    1. public static Sequence Jump([NotNull] Transform target, Vector3 endValue, float duration, float height, int numJumps = 1) {
    2.     Assert.IsTrue(numJumps >= 1, nameof(numJumps) + "should be >= 1.");
    3.     var jumpsSequence = Sequence.Create();
    4.     var iniPosY = target.position.y;
    5.     var deltaJump = (endValue.y - iniPosY) / numJumps;
    6.     var jumpDuration = duration / (numJumps * 2);
    7.     for (int i = 0; i < numJumps; i++) {
    8.         var from = iniPosY + i * deltaJump;
    9.         var to = iniPosY + (i + 1) * deltaJump;
    10.         jumpsSequence.Chain(Tween.PositionY(target, Mathf.Max(from, to) + height, jumpDuration, Ease.OutQuad))
    11.             .Chain(Tween.PositionY(target, to, jumpDuration, Ease.InQuad));
    12.     }
    13.     return Tween.PositionX(target, endValue.x, duration, Ease.Linear)
    14.         .Group(Tween.PositionZ(target, endValue.z, duration, Ease.Linear))
    15.         .Group(jumpsSequence);
    16. }
    I also reordered the parameters and edited this previous post. Will include the Jump() and LocalJump() methods in the next release.
    Please also update to version 1.0.15, it has a hotfix for the bug I just discovered: the first time a Sequence is created, it may play incorrectly in the case of chained tweens of the same type.
     
  42. NFMynster

    NFMynster

    Joined:
    Jul 1, 2013
    Posts:
    66
    Thank you, this works now.
    Will the new version with the Jump and LocalJump also include the tweens for TextMeshPro? Particularly the DOText and the DOCount? (I guess I can custom tween the docount as an int currently though)
     
  43. DungDajHjep

    DungDajHjep

    Joined:
    Mar 25, 2015
    Posts:
    173
    Hello, can I set nomallizeTime for tween like animation? @KyryloKuzyk
     
  44. yuliyF

    yuliyF

    Joined:
    Nov 15, 2012
    Posts:
    188
    Please, add some functions for change color in UI, like:
    LeanTween.colorText
    - it's more convenient
     
  45. NFMynster

    NFMynster

    Joined:
    Jul 1, 2013
    Posts:
    66
    Instead of the custom tween you mean?
    upload_2023-10-16_13-30-2.png

    Edit: Use Tween.Color
     
    Last edited: Oct 17, 2023
  46. KyryloKuzyk

    KyryloKuzyk

    Joined:
    Nov 4, 2013
    Posts:
    1,070
    The next version, no. I'm currently working on other features, but TextMeshPro support is definitely coming in the future.
    This is currently not supported, but I'm currently working on the SetElapsedTime() API, so adding the SetNormalizedTime() API would be very easy after that.
    It's already possible with the help of
    Tween.Color(UI.Graphic target, ...)
    . UI.Text is inherited from UI.Graphic, so all tween methods that accept UI.Graphic also work with UI.Text (and any other inherited types like UI.Shadow and so on).
    Also, to animate only the alpha channel of the text, you can use the
    Tween.Alpha(UI.Graphic target, ...)
    method.
     
    DungDajHjep and NFMynster like this.
  47. DungDajHjep

    DungDajHjep

    Joined:
    Mar 25, 2015
    Posts:
    173
    Amazing ! I would use this library if it supported normallize time, since Dotween doesn't seem to support that.
     
    KyryloKuzyk likes this.
  48. KyryloKuzyk

    KyryloKuzyk

    Joined:
    Nov 4, 2013
    Posts:
    1,070
    @DungDajHjep I'm glad to hear that! I should mention that tweens and sequences in PrimeTween are non-reusable, so caching them, and then reusing them later is not possible. Instead, in PrimeTween, you start tweens the same exact moment you need them. So in order to use the SetElapsedTime() and SetNormalizedTime() in the future, you'll have to first ensure that the tween is running, as described here. This approach doesn't impose any limitations on the complexity of animations you can do with PrimeTween, it's just a slightly different API paradigm that makes the user's code simpler in the majority of use cases and prevents performance issues.
    To be totally fair, DOTween has the Goto() method, so adding the SetElapsedTime() is as easy as adding this extension method to your project:
    Code (CSharp):
    1. public static class DOTweenExtensions {
    2.     public static void SetNormalizedTime(this Tween t, float normalizedTime) {
    3.         t.Goto(t.Duration(false) * normalizedTime);
    4.     }
    5. }
     
    Last edited: Oct 16, 2023
    DungDajHjep likes this.
  49. DungDajHjep

    DungDajHjep

    Joined:
    Mar 25, 2015
    Posts:
    173
    thanks you so much !
     
    KyryloKuzyk likes this.
  50. NFMynster

    NFMynster

    Joined:
    Jul 1, 2013
    Posts:
    66
    Am I misusing the delays here?
    Code (CSharp):
    1. PrimeTween.Tween.Delay(this, duration: .5f, target => OnTweenDone()).SetCycles(10);
    The OnTweenDone is only called ONCE - After the 10 cycles has passed.
    I was expecting it to be called 10 times. Doesn't get called at all if you set the cycles to infinite (-1).
     
    Last edited: Oct 17, 2023