Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Question Optimize Time.DeltaTime or alternative

Discussion in 'Scripting' started by Prudentibus, Apr 16, 2023.

  1. Prudentibus

    Prudentibus

    Joined:
    May 15, 2022
    Posts:
    10
    Hey there,

    I get used to use any (Vector/Mathf).Lerp function with Time.DeltaTime for smooth transition.
    But I noticed that on different platform the value for Time is different, and that's frustrates me, because whetn on PC transition might look smooth and fast, on mobile platforms it could take very long time.

    I already googled why it happening, so my question is:
    Is there a better solution for smooth transition for any visible transition between big numbers on various platforms by using Time.deltaTime properly or use alternative?
     
  2. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,070
    To be blunt about it, vanilla lerp doesn't play well with deltatime. (I'm too lazy to explain why.)

    If you really want to use lerps, try reading the following articles
    Improved lerp smoothing
    Frame rate independent damping using lerp

    And I've seen even better YT videos explaining how to make lerp frame-independent, try looking it up once you get behind the terminology.
     
    Prudentibus likes this.
  3. halley

    halley

    Joined:
    Aug 26, 2013
    Posts:
    2,364
    Lerp isn't meant for deltas or speeds. Lerp is meant for a transition from 0 to 1. You need to remember the ORIGINAL position, and the TARGET position and calculate where between them on a scale of 0 to 1. Every call needs to use the same ORIGINAL, not CURRENT value in the first argument.

    It's a common misuse/misunderstanding of Lerp to try to do something with Time.deltaTime there, but if the range is small you never reach the target and if the range is big you snap to the target. Even some big-name YouTube tutorial authors get this wrong (or abuse it knowingly with no explanation). If you ever see a Lerp with the CURRENT position in the first argument instead of the ORIGINAL position, you can mutter under your breath about how that author was sadly deluded.

    MoveTowards is meant for deltas or speeds. You do not need to remember the original position, you need to give the CURRENT position and the TARGET position and the desired maximum movement per usage (such as SPEED * Time.deltaTime).
     
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,517
    That's not a delusion.

    That's just a single-tap low-pass filter.

    Anyone who has taken a DSP class will instantly recognize what is going on:

    Here's the simplest cheesiest-possible low-pass filter:

    A = (A + B) / 2;


    By using Lerp() you can parametrically control the snappiness and filter shape with a single scalar term.

    It's not mathematically correct or anything but:

    - it works marvels for smoothing out a noisy signal.
    - the "memory" portion is tiny (just one sample)
    - the computation load is trivial (ADD and DIV, or if you prefer, ADD and ASR by 1 bit)

    Yes it is framerate sensitive... but framerate variances of even 300% are not even subjectively noticeable.

    And let's be honest: if there's more than 300% framerate variance nobody is playing that game anyway!

    Source: I do it all the time in almost 100% of my games, generally to smooth out any kind of noisy signal.

    Here's a single page of Mathf.Lerp() calls from Jetpack Kurt... green are ones that are used as a low-pass filter, all others are as a Lerp.

    poor_mans_lowpass_filter_1.png

    And here's a single page of Vector3.Lerp() calls from Jetpack Kurt, again green marking low-pass filter uses:

    poor_mans_lowpass_filter_2.png

    It's incredibly useful!

    It's even used in Unity's own UnityEngine.UI ScrollRect velocity damping!!

    See line 849 here or just search Lerp():

    https://github.com/Unity-Technologies/uGUI/blob/2019.1/UnityEngine.UI/UI/Core/ScrollRect.cs
     
    Ryiah likes this.
  5. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,070
    I'm also using them to smooth things out. I am a believer of "smearing" action across multiple frames whenever possible. It's highly subjective, but this let's me use simple, snappy, imprecise, or noisy drivers and still maintain the expensive-looking motion, with just the right hint of inertia.
     
    Ryiah and Kurt-Dekker like this.
  6. halley

    halley

    Joined:
    Aug 26, 2013
    Posts:
    2,364
    No, I get it, Kurt. I just don't like it. Making things approach a fixed limit on a curve is one thing, but if you'll forgive the rhyme, asymptotic is idiotic. I want to reach the target, I don't want to keep crossing Zeno's Paradoxical bridge in half steps forever. It feels sloppy and indeterminant.

    Obviously, do what you like. I just dislike how so many tutorials out there give advice to use it one way, and then we see so many newcomers trying to figure out why they have trouble with it when they don't understand the name "LinearInterpolationOrAsymptoticallyApproachIfUsedDifferently()".
     
    angrypenguin and Ryiah like this.
  7. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,070
    Hey I get ya, but if you think like I do, you never do asymptotic drivers, you just apply the final motion asymptotically. Sometimes. Who cares, as long as you don't make things wobble by pixel due to rounding errors. Ultimately animation will always be sloppy no matter what you do (unless it's strictly procedural and overly complex). It's just a matter of zoom.

    Last year I did a universal 2nd order dynamics math that does animation deterministically, and you can tweak several parameters for damping, springiness, acceleration etc. That's usually my key driver for the camera and everything. Then I do a low pass filter, similar to what Kurt said, and I really think this approach is the next gen from everything I did prior, especially the lerps and tweens I did back in the 2000's.

    There is some fine art / stylistic choice in letting the frames be whatever they want to be, not having everything nailed down deterministically. It's more akin to snapshotting some external unknowable process (i.e. cinematography) than having overt control over everything (i.e. rendering) and inadvertently making everything look plastic.

    That's just my opinion however, it's not that I have something against your way of doing it. But maybe you can open yourself toward new hybrid approaches and see for yourself if it suits you.
     
  8. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    7,606
    angrypenguin and halley like this.
  9. StarBornMoonBeam

    StarBornMoonBeam

    Joined:
    Mar 26, 2023
    Posts:
    209
    Addressing the problem of frame rates on multiple devices....

    I can only suggest that system clock might be used. And update would be removed and turned into an iteration. And you have to count 1 second and divide the milliseconds into how many frames per second it was supposed or intended to be. And then execute the new method update when you pass your fps (ms) execution frame.
    For example maybe if you had a cutscene and audio desync on some devices. I'm not entirely sure if things can be that bad but Id anticipate such an issue could be possible.
    Since your update will always be fast enough on it's own to tell if the system clock changed, it should be for 120 fps executing it's main method every 0.0083% of a second. Update is smaller than this value usually, and should squeeze some frames between game passes where only the system clock is checked to see if it's time to execute. If timing consistency was integral then that may be a more suitable update method. Though if device frame rate was unstable then frames could be missed or their computations occur but frames not visually represented.
     
    Prudentibus likes this.