Dear Game Developers, Stop Messing This Up!

แชร์
ฝัง
  • เผยแพร่เมื่อ 12 พ.ค. 2024
  • DeltaTime. This video is all about that mysterious variable that oh so many game developers seem to struggle with. How to use DeltaTime correclty? I got the answers and hope this video will help to deepen your understanding about how to make frame rate independent video games.
    0:00 - Intro
    0:34 - Creating The Illusion of Motion
    1:11 - Simple Linear Movement
    3:25 - But What is DeltaTime Exactly?
    5:42 - Fixed Updates
    8:22 - Movement While Changing Speed
    10:41 - Integrals And Why You Might Need Them
    13:17 - Approximations And Why They Are Fine
    14:30 - Movement Formulas
    15:03 - The Unforgivable Mistake
    16:54 - How to Lerp Correctly
    20:43 - Test Your Game!
    21:31 - Get Your Grade Here!
    My Games:
    ➤ Play Thronefall on Steam: store.steampowered.com/app/22...
    ➤ Join the Thronefall Discord: / discord
    ➤ Play Will You Snail on Steam: store.steampowered.com/app/11...
    ➤ Join the Will You Snail Discord: / discord
    For the game developers among you:
    ➤ Join our creative game dev community on Discord: / discord
    Hope you enjoy. :)
    #gamedev #indiedev

ความคิดเห็น • 1.6K

  • @JonasTyroller
    @JonasTyroller  10 หลายเดือนก่อน +1717

    Small corrections (I learn some things from you as well, how nice, haha):
    - Using Time.deltaTime in Fixed Update is actually fine in Unity cause it automatically returns Time.fixedDeltaTime depending on where it is called from.
    - Using Delta Time in fixed update still makes sense for various reasons (it keeps speed to units/second and helps when inaccuracies in the fixed update intervals occur)
    That means 10 free points to you if your read this, haha. Will keep updating this in case I got anything else wrong. :P

    • @Robyamdam
      @Robyamdam 10 หลายเดือนก่อน +48

      Can you do more of these please?, Maybe an episode on debugging or finding code related problems that don't seem to have an answer

    • @blockify
      @blockify 10 หลายเดือนก่อน +8

      dont these 2 corrections contradict eachother? or am I being dumb xD If deltaTime returns fixedDeltaTime while in the Fixed Update, then how can it keep speed to units/second and help inaccuracies?

    • @aksimilumaspvp7278
      @aksimilumaspvp7278 10 หลายเดือนก่อน +13

      @@blockify no because fixedDeltatime takes the inaccuraties and inconsistencies in fixedupdate into account, and deltaTime gives rhat fixedDeltatime.
      Point is in fixedUpdate
      fixedDeltatime==DeltaTime. There is no difference using one or another.
      Still, using either one can be helpful to get around inaccuraties(which can happen in fixedupdate if u use neither)

    • @wayfarergames
      @wayfarergames 10 หลายเดือนก่อน +2

      ​@@blockifyif it helps, you can think of multiplying by deltaTime or fixedDeltaTime as a sort of "per frame -> per second" conversion in unity! (You can also convert the other way by dividing by deltaTime, e.g. if you want to get the amount an object has moved in a single frame, you'd divide its velocity by deltaTime since in Unity velocities are usually per second)

    • @CyberAngel67
      @CyberAngel67 10 หลายเดือนก่อน

      It doesn't return fixedDelta time. If we go back to what I said in another comment, the correct answer is not A in fact non of the truly was the right answer. delta time is the time it took to process the last frame, the documentation backs this up. So when you run that in FixedUpdate, that means the normal delta and the fixed delta will be the same value, but one does not simply return the other. Physics is a fixed step, therefore both are going to equal the same value!

  • @tommysedin
    @tommysedin 10 หลายเดือนก่อน +504

    6:50 I would say that it's not pointless to multiply by fixedDeltaTime; Makes it easier to code consistent units (say if you're trying to follow SI units strictly, or if you have calculations in both Update and FixedUpdate that should follow the same unit). Also, if you ever end up changing the frame rate of the FixedUpdate, you'll have to change every single calculation.

    • @JonasTyroller
      @JonasTyroller  10 หลายเดือนก่อน +112

      Fair! :)

    • @zelos666
      @zelos666 10 หลายเดือนก่อน +73

      The physics will actually break if you change Time.timeScale and don't multiply by fixedDeltaTime, because fixedDeltaTime will change with the timeScale. Meaning it's actually not always the same value, if you have any kind of speedup or slowdown with timeScale in your game.

    • @ThePhoenix107
      @ThePhoenix107 10 หลายเดือนก่อน +31

      Just want to add that the code example did not need to be changed at all to be called for FixedUpdate. And that is because Time.deltaTime actually returns Time.fixedDeltaTime when called from within FixedUpdate.

    • @mrcreepypl
      @mrcreepypl 10 หลายเดือนก่อน +9

      @@ThePhoenix107 Cool to know, but I'll still stick with fixedDeltaTime for consistency and clarity.

    • @rhysvanderwaerden5518
      @rhysvanderwaerden5518 10 หลายเดือนก่อน +6

      ​@@zelos666it actually is the other way. The fixed delta time stays the same, but anything running in fixed time will become more granular in real time because fewer fixed steps will occur between frames. This is why you might need to reduce your fixed time step for slow motion.
      If you are modifying your fixed delta time for this purpose then you definitely need multiply by it in fixed update.

  • @leffeup8117
    @leffeup8117 10 หลายเดือนก่อน +1711

    As someone who litteraly had a math test earlier today on the subject of integrals, this was a great ego boost

    • @nobody.of.importance
      @nobody.of.importance 10 หลายเดือนก่อน +50

      I recall when I got into Math 251 Differential Calculus, I thought it was going to be some pretty insane shit, but it turns out we use it all the time without even realizing it. It's just so much more powerful if you know the fancy tricks. I cannot recommend enough that those who don't know at least differential calculus to learn it. You will not regret it.

    • @gogauze
      @gogauze 10 หลายเดือนก่อน +24

      ​@@nobody.of.importance*sigh* FINE. I'll go learn differental calculus this month.

    • @Nidhsa
      @Nidhsa 10 หลายเดือนก่อน +3

      @@gogauze im learning it in the fall

    • @nobody.of.importance
      @nobody.of.importance 10 หลายเดือนก่อน +4

      @@gogauze Knowledge is power! Good luck! Same for you Nidhsa c:

    • @juxyper
      @juxyper 10 หลายเดือนก่อน +2

      this is not only integrals, this is discrete integrals!

  • @grbrigsted
    @grbrigsted 10 หลายเดือนก่อน +618

    If you're not using fixed updates, you might end up clipping through walls from lag spikes, unless you're using rays to assert if the player has moved through a wall between the previous frame and the current.

    • @i_makegames
      @i_makegames 10 หลายเดือนก่อน +18

      correct me if im wrong but, this will only happen if you use a rigid body controller, not for example the player controller asset, also you dont need to code a ray check as you can just set the rigid body to 'continuous' or 'continuous dynamic'

    • @JonelKingas
      @JonelKingas 9 หลายเดือนก่อน +7

      im literally so new at game dev, im just pretty much using everything in fixedupdate, and what needs to execute fast for example key pressed in update, idk if its fine but it works fine, example in my game this:
      void Update()
      {
      if (Input.GetMouseButtonDown(0))
      {
      isShooting = true;
      CalculateShootDirection();
      }
      else if (Input.GetMouseButtonUp(0))
      {
      isShooting = false;
      }
      if (isShooting)
      {
      CalculateShootDirection();
      }
      }
      void FixedUpdate()
      {
      if (isShooting)
      {
      shootTimer += Time.fixedDeltaTime;
      if (shootTimer >= shootingDelay)
      {
      Vector3 bulletVelocity = bulletSpeed * shootDirection;
      GameObject bullet1 = Instantiate(bulletPrefab, bulletSpawnPoint1.position, Quaternion.identity);
      bullet1.GetComponent().velocity = bulletVelocity;
      GameObject bullet2 = Instantiate(bulletPrefab, bulletSpawnPoint2.position, Quaternion.identity);
      bullet2.GetComponent().velocity = bulletVelocity;
      float rotationAngle = Mathf.Atan2(shootDirection.y, shootDirection.x) * Mathf.Rad2Deg;
      bullet1.transform.rotation = Quaternion.Euler(0f, 0f, rotationAngle);
      bullet1.transform.Rotate(Vector3.forward, 90f);
      bullet2.transform.rotation = Quaternion.Euler(0f, 0f, rotationAngle);
      bullet2.transform.Rotate(Vector3.forward, 90f);
      shootTimer = 0f;
      }
      }
      }
      private void CalculateShootDirection()
      {
      // Calculate the shoot direction based on the player's transform
      shootDirection = bulletSpawnMainPoint.up; // Assuming the player's forward direction is along the X-axis
      shootDirection.Normalize();
      }

    • @hexagon_
      @hexagon_ 9 หลายเดือนก่อน +1

      Orange grenade lifestyle

    • @grbrigsted
      @grbrigsted 9 หลายเดือนก่อน +2

      Neutral Milk Hotel

    • @notChocoMilk
      @notChocoMilk 9 หลายเดือนก่อน +1

      so that’s how i fix that.. too bad i’m already making a new player controller

  • @metalstarver642
    @metalstarver642 10 หลายเดือนก่อน +198

    Actually things get 100x more complicated if you have non-constant forces, you need to lookup numerical integration (initial value problem). Your recommended way is called Leapfrog integration. It can work really far from accurate if you have spring forces (with springs you need tiny timestep or other more sophisticated methods which usually are not suitable for real-time).

    • @astecheee1519
      @astecheee1519 9 หลายเดือนก่อน +5

      I feel like springs are better expressed with approximations in games.

    • @drstrangecoin6050
      @drstrangecoin6050 9 หลายเดือนก่อน +4

      Is a second order taylor series the wrong thing to do here?

    • @metalstarver642
      @metalstarver642 9 หลายเดือนก่อน +4

      @@drstrangecoin6050 It depends. For springs or gravity (N-body sim) to get stable results Taylor series won't be enough. You would need implicit methods for accurate and stable results (too slow for real-time). But for games springs could be done without forces in more stable way (e.g XPBD). Stability of gravity forces usually not an issue unless you're doing Solar system simulations or the like (in which case parametrized elliptical orbits may be better option for game). For a game maybe first check implicit Euler and then XPBD if it fails, otherwise start faking it.

    • @ckjdinnj
      @ckjdinnj 8 หลายเดือนก่อน +1

      Implicit is used all the time in games.
      In fact they showed a common example in the video …
      velocity = velocity + acceleration * deltaTime
      position = position + velocity * deltaTime
      2nd order Taylor series is fine for most use-cases.
      If you have to support some wildly stiff springs or need a high degree of accuracy then you could try rk4.
      p0=initialPos
      r=restingPos
      v0=initialVelocity
      k=springStiffness
      dt=deltaTime
      m=mass
      f1=k*(r-p0) // force
      v1=dt*f1/m+v0
      p1=0.5*dt*v1+p0
      f2=k*(r-p1)
      v2=0.5*dt*f2/m+v0
      p2=0.5*dt*v2+p0
      f3=k*(r-p2)
      v3=0.5*dt*f3/m+v0
      p3=dt*v3+p0
      f4=k*(r-p3)
      v4=dt*f4/m+v0
      v_final=v0+(f1+2*f2+2*f3+f4)*(dt/m)/6
      p_final=p0+(v1+2*v2+2*v3+v4)*dt/6

    • @ckjdinnj
      @ckjdinnj 8 หลายเดือนก่อน +2

      Performance cost is relative as well. It’s all about scale of use. If you wanted a 3rd person spring arm camera and it needed to be super stiff/snappy one use of rk4 would be fine. However if you are setting up a dense foliage section where foliage physically interacts with the player then you’d probably just use a simple implicit approach with
      v_final=v0+dt*k*(r-p)/m
      p_final=v_final*dt+p0

  • @Ochros
    @Ochros 10 หลายเดือนก่อน +240

    21:50 From your testing scheme, it's actually possible to get everything wrong and also the -10 points, leaving you with a grading that is undefined according to your evaluation :P (if I didn't miss anything)

    • @Aeroxima
      @Aeroxima 10 หลายเดือนก่อน +33

      Negative F!

    • @Cynadyde
      @Cynadyde 10 หลายเดือนก่อน +68

      being undefined, there's every chance we hit a negative integer overflow and land on a grade no less than 150

    • @madmax404
      @madmax404 10 หลายเดือนก่อน +31

      In this case I think you can just give yourself 4294967285 points

    • @EmersonPeters
      @EmersonPeters 10 หลายเดือนก่อน +14

      Spoken like a true game tester!

    • @Jonskipvp
      @Jonskipvp 8 หลายเดือนก่อน +4

      @@madmax404 the only winning move is not to play

  • @klikkolee
    @klikkolee 10 หลายเดือนก่อน +23

    I'm going to contest question 2 based on the wording.
    The presentation of a frame can be conceptualized as happening at specific instant of time, but the game logic of a frame takes meaningful time to happen. If I just see phrases like "the current frame" and "the last frame" in reference to timing and without further indication, I will interpret that as referring to those spans of time. In the context of timing, frames have a start and an end, and that end is before the frame's presentation. Since each operation can be conceptualized as contributing to a specific frame, the end of a frame is the same as the start of the next.
    You don't know when the current frame will finish or when it will present, but you do know when it started. A game engine is going to use the most recent frame-time estimate it can, and that would be the time between the start of the current frame and the start of the previous frame. This is more consistent with the wording of option B than the wording of option A, and it is consistent with the wording in the Unity script reference for Time.deltaTime: "The interval in seconds from the last frame to the current one"

    • @rumbleball542
      @rumbleball542 2 หลายเดือนก่อน

      Thank you.

    • @Julianiolo
      @Julianiolo 2 หลายเดือนก่อน +1

      wtf this is exactly what I just wrote lol. With a lot more fancy words sprinkled in though

  • @Randy14512
    @Randy14512 10 หลายเดือนก่อน +596

    I don't code, but I am a physics nerd and saw delta time and it peaked my interest. Was not disappointed to see the explanations of calculating changes in distance as a function of time when not accelerating, when accelerating, and with a changing acceleration value. With the questions that were math based and not definition based other then syntax i am happy to say I got the idea right lol.

    • @superscatboy
      @superscatboy 10 หลายเดือนก่อน +58

      For future reference: It *piqued* your interest.

    • @oisyn-
      @oisyn- 10 หลายเดือนก่อน +91

      @@superscatboy Maybe his interest curve reached a local maximum, so it really did peak his interest.

    • @superscatboy
      @superscatboy 10 หลายเดือนก่อน +7

      @@oisyn- Or maybe that's just a load of old bollocks 🤷‍♂️

    • @baitposter
      @baitposter 10 หลายเดือนก่อน +8

      ​@@superscatboy
      Well, my interest definitely *peaked* when seeing the title of this video

    • @nathangamble125
      @nathangamble125 10 หลายเดือนก่อน +18

      @@baitposter So your interest decreased when actually watching the video?

  • @MrWolfheat
    @MrWolfheat 10 หลายเดือนก่อน +430

    I think that in the latest unity versions using deltaTime in fixedUpdate will automatically use the fixedDeltaTime internally so you do not need to change this. Unity implicitly understand which one to use by the context it is used in.

    • @CyberAngel67
      @CyberAngel67 10 หลายเดือนก่อน +14

      it won't auto use the fixed delta time, the timing will just be identical.

    • @1vader
      @1vader 10 หลายเดือนก่อน +5

      It's not only in the latest Unity version. I recall hearing about this behavior at least several years ago.

    • @delphicdescant
      @delphicdescant 10 หลายเดือนก่อน +70

      Wow that's kind of terrible API design.
      Would be a lot better if using deltaTime in fixedUpdate were an error.
      Implicit/hidden behavior is an evil that you might expect to see in the realm of web dev frontend nonsense, but not in applications programming.

    • @DiThi
      @DiThi 10 หลายเดือนก่อน +39

      In my opinion, the best API design would be to have the delta time as argument to the update functions, that way it's impossible to mess it up.

    • @milanstevic8424
      @milanstevic8424 10 หลายเดือนก่อน +7

      Unity's API design choices are notoriously bad. Thankfully once you learn all the shitty things and minefields it's full of, you can safely ignore it and build up your own software more robustly. But be warned, Unity is a hell to learn.

  • @sammtavv
    @sammtavv 10 หลายเดือนก่อน +529

    I didn't know i always wanted a video from Jonas directly to the developers. Gotta love these videos!

  • @tcatdev
    @tcatdev 10 หลายเดือนก่อน +45

    When people misuse lerp you can really feel it in the gameplay. I did a little different than you though. I recorded the start position and start time, then I use the elapsed time to calculate the lerp factor in each frame.
    I also like using cosine instead of sqrt, because it gives a more natural feel. The formula is (1 - cos(x * PI)) / 2, where x is the elapsed time.

    • @bastian_5975
      @bastian_5975 10 หลายเดือนก่อน

      Are you saying you did position = lerp(startingPosition, endingPosition, 1-cos(x*pi)/2)? Because that would cause it to go back and forth between the start and end, not approach but never reach the end.

    • @gajbooks
      @gajbooks 10 หลายเดือนก่อน +1

      @@bastian_5975 It should probably be cos(1/(x+2)*PI), which is really just a differently smoothed version of 1 - (1/(x+1)), where x is elapsed time in both scenarios. (There's an absolute ton of "sigmoid" functions you can use to infinitely approach a number.) The delta-time lerp works though, just it makes a little less sense logically because instead of lerping between two fixed points, you end up lerping between the destination and the previous location.

    • @bastian_5975
      @bastian_5975 10 หลายเดือนก่อน

      @@gajbooks at first I thought you meant cos(1/(pi*(x+2))), but cos(pi/(x+2)) looks so much better that I think you mean that.
      And are you saying that the function you defined was a sigmoid function or that sigmoid functions are a class of functions that also achieve that effect?

  • @XoIoRouge
    @XoIoRouge 7 หลายเดือนก่อน +29

    I love the presentation of this video, with an actual test. The whole "YOU WILL BE GRADED JOKE" actually motivated me to do well on this test that no one will see. I've seen many youtubers educate with information, by just telling us the right answer, showing it in examples, with great animations to help visualize. That process works, but I think many content creators forgot how effective it is to challenge our knowledge. At 3:41, despite me using deltaTime in many places, I realize that... I'm not EXACTLY sure which of these four are true.
    Thank you for challenging my knowledge, and because of that, you've stuck out as a memorable youtube educator. I've subscribed and I look forward to learning more from you.

  • @Random-kj1go
    @Random-kj1go 10 หลายเดือนก่อน +59

    please we need more of thisss this is the exact technical info no one talks about and it even has a visualisation very good video 10/10

  • @Ombarus
    @Ombarus 10 หลายเดือนก่อน +35

    Very impressed, you've covered many of the pitfalls. Just two remark: Fixed Update is useful to avoid costly exponent which are very common in Physics calculation because if you have a constant delta time then the linear approximation is good enough (so the "bad" lerp in a FixedUpdate would work just fine). The big drawback with FixedUpdate is that you'll usually notice "jerking" as one frame you'll update 3 times, but then the next frame only 1, then the next 2. Usually to fix this you need to extrapolate the difference between the current frame's deltatime and the FixedDeltaTime.

    • @nathanielguggenheim5522
      @nathanielguggenheim5522 10 หลายเดือนก่อน +2

      Or avoid FixedUpdate() altogether and call Physics.Simulate() by yourself in Update() after disabling automatic PhysX Update. Actually the only method I know to avoid Unity's microstuttering.

  • @madmax404
    @madmax404 10 หลายเดือนก่อน +3

    Thanks for the Lerp fix! This is something I pretty much gave up on after I realized the solution would be a easy to mess up, and almost completely just changed to using spring-damp systems, though partially because they're also often just better.
    Though I'd say that the "simple" solution to calculating per-frame movement deltas is not ok 9/10 time but probably closer to 99/99.9% of the time.
    I've never actually brushed against it but have had a lot of pain due to different update rates simply ending up with different results, and inconsistent amounts of FixedUpdates causing frame pacing issues. For the Xbox One port of Thief of Thief for example, I ended up doing a hack that connects Update and FixedUpdate rates as long as they don't want to be too far from each other and managed to remove almost all frame pacing issues (which were bad otherwise) from the game.
    I've had to do this only once, but I had a sprint-joint system smoothly controlling the camera in Among The Trolls. If the framerate got REALLY bad, the system went completely out of whack. So for that I implemented custom sub-stepping where the calculation was always calculated with an almost non-changing deltatime but just repeated enough times during a frame if the framerate was bad. This is how FixedUpdate also works in essence, but with FixedUpdate this can cause those cursed problems where the frames get longer because FixedUpdate is called more, if FixedUpdate gets even slightly expensive.
    Closest solution I have to syncing 2 clients with different frame times (in absolute time) was a server-time synchronized RPC where, I decided to trigger the event on the slower-updating client even if the trigger time wasn't yet reached as long as if the estimated time of the next frame would be even more off. Of course this also used the last frame's frametime though but made some events seem almost magically in-sync as long as I could schedule the event far enough in the past (like 300ms).

  • @IvanLeben
    @IvanLeben 10 หลายเดือนก่อน +80

    There is actually another layer of complexity here, which even experienced games developers often miss: regardless of how much time has passed between your consecutive update calls, the monitor typically can only present images spaced at a fixed interval from each other - the refresh rate of the monitor. The only exception here would be if you are using a variable-refresh monitor with a GSync or FreeSync technology. If you are updating your game with variable deltaTimes, but presenting those frames on the screen at a fixed rate, you will create what we call "microstuttering". The animation will overall keep correct pace with the wall clock, but it will appear jerky, unsmooth. Unless you are using GSync, you should only ever update your game in increments that are a multiple of the monitor refresh rate and then tell the rendering system to present these frames at the correct time in the future - if you are updating the game for X milliseconds, then the frame you've generated should be presented exactly X milliseconds from when the previous frame was presented. This technique is callled "frame pacing" and fixes microstuttering. Note that modern game-engines like Unity and Unreal might automate frame-pacing for you behind the scenes, by feeding you deltaTimes and presenting the frames as appropriate (support might also depend on the platform you are shipping the game on).

    • @wakannnai1
      @wakannnai1 6 หลายเดือนก่อน +7

      If your engine is developed properly, DeltaTime should be tied directly to the update of a frame. Most modern engines (Unreal Engine, Unity, and most AAA Engines) tie DeltaTime directly to the update of every frame. This by definition means that each tick is tied to the update of a frame.
      In the scenario you presented this is not what happens. If your actual frame update is not in sync with your refresh rate on your monitor, you'll typically see frame tearing (since almost all engines will queue at least a frame in advance in the back buffer and update the screen on each refresh). Screen tearing happens since the new frame that was in the process of rendering in the back buffer is being pushed to the screen in an incomplete state.
      Microstuttering really happens when you're close to the target refresh rate. Since there's some variability in each frames workload (both on the CPU and GPU), frame completion may not fall exactly on the expected interval to update (ie 1 frame may have taken 17ms rather than 16.5ms to complete rendering). In order to avoid this, a lot of devs will try to exceed performance from the target enough to minimize Microstuttering. It has nothing to do with updating your game with variable DeltaTimes. It has more to do with frame consistency.

  • @enreeper
    @enreeper 10 หลายเดือนก่อน +118

    Way back before I even knew about delta time I used to have my games code run at 120fps and didn't noticed any weird behaviour, but as soon as other players with 60hz displays played the game everything was in slow motion running at half the speed, they often commented the game feels slow and me and my friend playing at 120 allways wondered what do they mean until I realised this issue.

    • @DOSRetroGamer
      @DOSRetroGamer 10 หลายเดือนก่อน +8

      Lol

    • @JonasTyroller
      @JonasTyroller  10 หลายเดือนก่อน +36

      Haha. Oh, no. :D

    • @blockify
      @blockify 10 หลายเดือนก่อน +6

      haha i too didn't realise for ages because since I never did anything big scale the fps stayed relatively consistent

    • @inkedalien
      @inkedalien 10 หลายเดือนก่อน +1

      same with us lol tested it out by racing each other in different refresh rates haha

  • @APaleDot
    @APaleDot 10 หลายเดือนก่อน +146

    For those confused about the lerp section, I have a really easy way to think about it intuitively:
    If your "lerpSpeed" is 1, then the base of the exponent (the number on the bottom) is the portion of the distance you want to cover in one second. So in the video this number is 0.5 which means the character covers 1/2 the distance to the goal every second. The reason this works is because when you do this multiple times in a row, the distance decreases exponentially. So, if you imagine your frame rate is 4 frames per second, then in the first frame the character covers 0.5 ^ 0.25 of the distance (because deltaTime is 0.25), and the next frame the distance will be less but they will still cover another 0.5 ^ 0.25 of _that_ distance. So the total distance covered will be (0.5 ^ 0.25)(0.5 ^ 0.25), which if you remember your exponent rules is equal to 0.5 ^ 0.5. In other words when you exponentiate like this, the deltaTime in the exponent adds linearly every time you lerp. In this example, if you lerp every frame for one second (that is 4 frames) then the exponent adds up to 0.5 ^ 1. In other words, you cover half the distance in one second, regardless of your deltaTime, as I stated in the beginning.
    EDIT: as explained in the replies, the base of the exponent actually represents the portion _remaining_ after 1 second, not the portion covered after 1 second, because you start at t = 0 which would give a blend value of 1, so we use 1 - 0.5^t instead (or Jonas puts the current position in the second parameter of lerp, which is equivalent)

    • @NXTangl
      @NXTangl 10 หลายเดือนก่อน +2

      For this reason, I would use Math.Exp(-lerpSpeed * deltaTime).

    • @pixelz3040
      @pixelz3040 10 หลายเดือนก่อน

      Just want to point something out here, cause this kinda bothered me. You are correct in that the reason for the deltaTime being in the exponent is so that they add to 1, but the total distance covered is NOT just the product of the blends. You can easily see this if you use a base other than 0.5.
      Assuming you have the function laid out like Jonas did, where the target position occurs when the blend is 0, then the position of the snail after n frames is going to be (target_position)(1 - (product of all the blends)). You can deduce this through induction with the lerp function. Lets say that our blend is 0.1 ^ 0.25, where the 0.25 is our deltaTime, just like in your example. Initially, the snail's position is 0. After 4 frames, or 1 second, the snail's position will be (target_position)(1 - (0.1 ^ 0.25) ^ 4) = (target_position)(1 - 0.1) = 0.9(target_position). After 4 frames, the snail moves 90% of the distance, not 10% as you implied.
      Fundamentally, what you're saying is helpful, but I saw the comment and got caught up on that snag for a while, and it kept me from truly understanding what was going on. Also, I agree with @NXTangl, using the built in exponential function is nice because then you don't have that arbitrary base and the speed is more directly controlled by lerpSpeed.

    • @feha92
      @feha92 10 หลายเดือนก่อน +1

      > So in the video this number (lerpspeed) is 0.5 which means the character covers 1/2 the distance to the goal every second
      No, in the video you cover 0.3 of the distance every second because of that number (lerpspeed) being 0.5.

    • @APaleDot
      @APaleDot 10 หลายเดือนก่อน

      @@feha92
      No, "this number" refers to the base of the exponent, which is 0.5 in the video. I also say that I'm setting lerpSpeed to 1 for simplicity. lerpSpeed is also 1 in the video IIRC, so I'm not sure how you mixed that up.
      Edit: actually, lerpSpeed is 0.5 in the video, so it makes sense you got mixed up. But I still said "if lerpSpeed is 1".

    • @APaleDot
      @APaleDot 10 หลายเดือนก่อน

      @@pixelz3040
      You're right, the base of the exponent is the portion _remaining_ after one second, not the portion covered. Those two numbers just happen to be the same when the base is 0.5, my bad.
      I personally still like to use the arbitrary base because the meaning of the base is clear when the exponent is 1, and I don't want to think about a base of 1 / 2.718. lerpSpeed controls the speed the same way in either case.

  • @LethalChicken77
    @LethalChicken77 10 หลายเดือนก่อน +7

    You actually do want to multiply by fixedDeltaTime in FixedUpdate a lot of the time, to ensure that your speeds are in units per second and the numbers in the inspector actually have meaning. It's also needed for more advanced custom physics, used in the integrations.

  • @baralike8206
    @baralike8206 10 หลายเดือนก่อน +3

    I think this is a great subject and something that many lack a good understanding of, but in my opinion this video too shows a lack of understanding of deltaTime.
    My biggest problem with this video's explanation of deltaTime arises in the explanation of why alternative b) is wrong in the first question (around 4:18). This video seems to present the idea that a frame should represent what the state of the program is when the frame is presented, while in reality, a frame represents what the state of the program was when the frame's update function began (when deltaTime was measured, to be precise). This means we're not using "the last frame's deltaTime as an approximation for the current one's," we are instead rightfully using deltaTime as the time between the last update call and the current one, because that gives us the state of the program at the time of updating.
    This also means that deltaTime does not "always have a 1 frame delay" (5:34) as an explanation for why lag spikes are 1 frame off. Instead, the state of the program that a frame is presenting is always at a 1 frame delay from the current state of the program. There is no special feature of deltaTime making it 1 frame behind.
    Furthermore, in any well-designed double-buffer renderer, the previous frame should be drawn on the gpu while the current frame is updating on the cpu. Once updating has completed, the previous frame is presented as the current frame, making the presented frame TWO frames behind the current state of the program. (+1 for every additional frame buffer)
    Other than that, I think this video explains things well and was fun to watch. A quick point to make is that for the explanation of the last question, the idea is presented that an exponential function is essential to achieve the desired result, while any function beginning at 0 and approaching 1 would work, such as 1 - 1/(1 + deltaTime * lerpSpeed), removing the need of Math.Pow.
    I guess I'll come across as another know-it-all, but I just wanted to share my understanding of the topic and I'll be happy to discuss it further!

  • @Zicrus
    @Zicrus 10 หลายเดือนก่อน +54

    3:48 This could actually be A or B depending on your definitions. I picked B, because it's the time between when the current frame started being processed and when the previous frame started being processed. If your definition for the time of a frame is when it is done processing, then A is the correct answer. I view the start of the frame as the true time, since that is also when inputs are registered, so the actual frame that is being displayed is slightly behind, not the other way around.

    • @mcarr87
      @mcarr87 10 หลายเดือนก่อน +21

      Just to add on to your comment, the video is wrong here as per reasonable definitions. The term 'current frame' always refers to the one you're currently processing. 'deltaTime' is calculated at the start of the processing of the current frame by comparing the time to the time the previous frame began processing. deltaTime is essentially how long the last frame took to process from start to end (where 'end' is the start of the current frame).
      "Time elapsed between the last frame and the one preceeding it" is a not a good definition of deltaTime because the frame before the last one has no relevance. The current frame's deltaTime value is calculated in the current frame and not at the end of the previous one. As per Unity's own documentation for Time.deltaTime it says it's "The interval in seconds from the last frame to the current one".
      I believe the error is largely due to representing frames as a point in a timeline when something is rendered on the screen. At some time, typically very shortly after that rendered frame point on the timeline, the deltaTime value will be calculated. The only relevant frames in the calculation is the previous frame and the current frame.
      Carrying on from this the video then describes deltaTime having a "1 frame delay" which is also stated and described confusingly. Obviously deltaTime is not going to be related to how slow the current frame is because it can't predict the future. So the best value it actually could be: the previous frame's calculation time, is essentially what it actually is. Describing that as a "1 frame delay" doesn't really make sense.
      Obviously here the video is referring to deltaTime in relation to something moving on screen and pointing to how the object moves only a little bit on screen on the frame that took a long time and then has the larger jump on the next frame. Saying that "deltaTime always has a 1 frame delay" because of this particular example is not reasonable. deltaTime is not delayed, it is the correct value for when it was calculated. Nothing prevents a programmer from calculating their own deltaTime equivalent value and moving objects with that right before rendering. Time.deltaTime is not delayed, you have just chosen to use it in a way that gives a result that you refer to as having a delay.
      If anyone was confused by the 1 frame delay part of the video and curious, the way the deltaTime value would work after a slow frame is is:
      If a game was running at 60FPS on Frame A, Frame B's deltaTime would be ~0.0166s. That's how long it was from the start of Frame A to the start of Frame B.
      If Frame B was then slow and took 0.1s (10FPS) to complete, Frame C's deltaTime value would be 0.1s
      Basically the frame after the slow frame would see the larger deltaTime value.
      Not a bad video otherwise, but that section in particular I think would be very confusing to programmers trying to learn about deltaTime. I believe conceptually it's essentially correct, but by representing frames in relation to deltaTime in that way and slightly misrepresenting when deltaTime is calculated it makes something fairly simple much more confusing.

    • @technorazor976
      @technorazor976 10 หลายเดือนก่อน +2

      I understood it that way too, thanks for confirming! +10 points to me!

    • @mcarr87
      @mcarr87 10 หลายเดือนก่อน +5

      And I just want to say that I don't like leaving some big comment like that, I just needed to write that much to explain everything.
      Obviously Jonas seems to be great at what he does and has made an excellent video. I know I'd hate making videos like this because it'd be very had to not make errors or poorly represent some things even if you know them well yourself in reality. I'd not want to have to see comments like mine above, but know that it's only left in the interest of helping clarify those elements from the video for anyone confused or off-put by them.
      I'm sure you (Jonas) understand what I've explained yourself and just (in my opinion) didn't express them adequately in that small part of the video.

    • @Gamesaucer
      @Gamesaucer 10 หลายเดือนก่อน +4

      @@mcarr87 Your comment is far more confusing than the video is. There are a few reasons for this.
      Firstly, there are two entirely contradictory definitions of a "current frame" at play here, which you don't seem to realise. On their own, both definitions are valid, but the one you present here has some issues in its broader context.
      You seem to define a "frame" as the routine that runs to produce it. In that sense, the current frame is indeed the one you're processing. But then a frame is a process and not a point in time. This contradicts with the definition of deltaTime in the Unity documentation you quoted, "The interval in seconds from the last frame to the current one". That one notably _does_ define a "frame" as being a point in time, as evidenced by it not saying "from the _start_ of the last frame".
      One important problem with your definition is that updating the game state is not linked to visuals whatsoever. A game could poll for inputs twice as often as it renders a new frame. These are still two game updates, but there is only one frame rendered. If you define a frame as a process, you'd have to exclude the time spent updating the game state, and only include the rendering time. But that's demonstrably not the value that deltaTime contains.
      The other definition of a frame is "the image being shown on the screen". This is a far more intuitive definition, and how most people understand such terms as "fps". There are 60 images being shown to me per second. And whatever is being shown to me at any given time, is the "current" frame. This frame is shown to me all at once and does not change afterwards until the next frame arrives. Thus, the moment it appears on my screen is a single point in time and not a process.
      Reading the definition of deltaTime again, this makes a lot more sense. Because the "current frame" is what you just finished. And deltaTime is indeed the space between those points in time by all definitions.
      You say that the way this definition is worded in the video is inaccurate, but that is simply not true. "Time elapsed between the last frame and the one preceding it" is a perfectly valid way of describing it, so long as you take "last" to mean "most recent" over "previous". The current frame is the most recent frame, and therefore the current frame can also be described as the last frame. This is not a strange way to use English, and should not be confusing for someone who speaks the language well enough to watch English videos on TH-cam and writes English comments.
      Additionally, I strongly disagree with that a "1 frame delay" is a bad way to describe what happens. Of course, the variable itself isn't delayed. Because it's defined with that delay already built-in. If I told you what I ate yesterday, my statement isn't delayed by one day. But that doesn't mean that your knowledge of what I ate isn't!
      The latter is the "delay" the video refers to. The example is clear about this as well: the frame shown after the lagspike does not take the lagspike into account exactly because that frame is being calculated as if it will render in the same amount of time that the last frame did. Regardless of what you're actually building, it is theoretically impossible to react within 1 frame to the time it takes to render just by reading the deltaTime variable.
      In short, it takes exactly one frame before you can react to how long a frame takes to render. I'd like to ask what you would describe this effect as, if not a "1 frame delay." This description has nothing to do with motion; it's a factual description of what you observe when you look at the game frame by frame. It takes one frame to adjust to a frame taking longer to render. You cannot adjust immediately. This is the definition of a delay.
      Don't get me wrong, I agree that there are ways in which the video could have been clearer. I just don't think that the things you take issue with are the problem, and that the alternatives you provide make things less clear rather than more clear.
      What the video really needed is not a change in definitions, but a more precise and consistent use of language. "Last" and "current" typically have the same meaning, but it'd be clearer if you stuck to one. It'd also be helpful to distinguish a "frame" as what's being shown, from an "update" as being the process to create it. And possibly a few other similar things. The content and presentation itself is fine and doesn't need to be changed, the script for the video really just needed one more editing pass.

    • @mcarr87
      @mcarr87 10 หลายเดือนก่อน +11

      @@Gamesaucer I appreciate your arguments and while I don't disagree that much of this depends on your particular definition, I don't agree that in this context of programming the definition of 'current frame' would only refer to the frame most recently output to the GPU. While not used too commonly as a direct term in the Unity docs and variables, you'll only find "current frame" referring to the one currently being processed that would next render (e.g. OnDemandRendering.willCurrentFrameRender) unless referencing something selected in a timeline like in the Profiler. Also I was directly referring to where the video's uses the phrase "the frame currently being processed".
      I 100% agree that a frame can and often does refer simply to the image presented to the screen, and the duration of that image on the screen in a standard, single buffered game would be determined by how long the following frame takes to update and render. That's not in question.
      But you bring up a great point that I didn't bother with because I'd already written too much before, and that is how a game could have multiple Updates without rendering a frame if it wanted. Alternatively you could have things like double or triple buffering that could delay the rendering of a frame until after other queued frames had rendered. To me, both of these are great arguments for my point.
      First, going off your concept, lets say you're in Unity with a disabled Camera object and you manually called Render() every 3rd frame. Here you have 3 Updates over 3 frames (as per Unity's definition of a frame. See e.g.: "Update[()] is called every frame") where only 1 of them is something drawn to the screen. You also have 3 different deltaTime values across those frames, 2 of which can't be said to have any relevance to what was drawn on screen last.
      You could also run your game's multiplayer server without rendering anything ever and it still has deltaTime and what most refer to as a frame rate (including Profilers, etc). You could argue that without rendering anything there is no 'frame rate' if you wanted, but that only diminishes your arguments because deltaTime still exists and is still calculated in the way I said it was without any relevance to what was drawn or if anything was drawn at all.
      The same type of example can be given for multiple buffering of frames where the deltaTime does not relate to what was last drawn on screen.
      I don't think in the context of programming your point "the moment it appears on my screen is a single point in time and not a process" has much validity. For one, saying a frame is a point in time doesn't really relate to the concept being discussed which is to do with the duration of a frame. Secondly even if you were to try to talk about it as a singular moment in time, what moment is that? When the LCD monitor draws the first line or the CRT's electron gun starts emitting or when the end of the image is finally displayed? What if the frame rate is faster than the monitor and it never finishes?
      I know that's overly pedantic, but it's just to illustrate that that is not a consistent or really even well definable thing and doesn't actually relate to actual programming and deltaTime.
      I don't really want to continue, but I'll quickly address your points on "1 frame delay" which I also find a bit odd.
      Saying what you ate yesterday is completely different from deltaTime. When deltaTime is calculated by Unity when a new frame begins processing, that is not a value telling you about something from the past. That is an immediate, current time difference between right now and back then. If it's referred to on the next line it's extremely current and relevant. You could say it's less 'current' later in the frame processing, but that depends entirely on how it's used. This is why I mentioned how you could use your own delta time calculation for rendering if you really wanted something more current for the frame you're processing than deltaTime.
      To say it has a delay is to proscribe a very weird definition to it. It is what it says it is and it does not give a delayed value at any point after its value is set. It's always 100% accurate as per what it is defined as being the value of. You know immediately at the start of processing a frame what the time the last frame took, there's no delay. That's the point of the value. To say it has a delay would be to give it the definition of "this is how long this frame will take, but you won't know until next frame because it has a 1 frame delay".
      I feel like this sort of discussion comes across as antagonistic and I apologise if it comes across that way. I also expect this could be one of those things where it's an ongoing back and forth, but I don't want to do that. I will freely admit that there's validity to the video's way of putting it and taken with certain definitions it's not wrong. This is what I said in my original post. I just don't believe in the context of programming, which this is, it was stated in the most valid and coherent way.

  • @Pontypants
    @Pontypants 10 หลายเดือนก่อน +7

    I am one of those. I know everything. No need for pen and paper. I already know. Even what I don't know I know... And then some..

  • @Bobsteperous
    @Bobsteperous 9 หลายเดือนก่อน +6

    Now THIS is the kind of tutorial i need, ive had enough of people just telling me what to put in to get my desired output, and i need that perfect level between talked to like a baby, and expecting im Einstein. You hit that nail right on the head.

  • @BicycleName
    @BicycleName 10 หลายเดือนก่อน +52

    For anyone interested in learning more about numerical integration, there's a whole range of other schemes you can apply which have different stability properties based on the deltaTime and the equations of motion of the players. Here at 8:22, if I can recall properly, he first uses Euler Forward then Euler Backward and after that, Crank-Nicolson. If you had a more complicated movement, you could as well switch to a spicier scheme (like Runge-Kutta) but it's propably over-engineering the task you're trying to achieve.

    • @Puukiuuki
      @Puukiuuki 10 หลายเดือนก่อน +4

      True, although this makes the difference between explicit (forward Euler) and implicit methods (backward E, C-N) appear very similar, since there is only a time dependence here. Normally you will need to solve a system of equations, which makes the thing inherently stable. A good example is the exponential speed case, where an explicit method can easily overshoot.

  • @mathijsfrank9268
    @mathijsfrank9268 10 หลายเดือนก่อน +23

    It is called FixedUpdate, but that doesn't mean it is actually 100% fixed. It tries to run in fixed intervals. However this will never be exactly right, either because of cpu cycles or if a fixed update exceeds its time budget. This will most likely be insignificant in most cases, but there is still a reason to use fixedDeltaTime for this.
    For example if you run physics in this fixed update and it always takes just a tiny bit longer than expected, the error can add up over time and without fixedDeltaTime it might explode your physics.

    • @JonasTyroller
      @JonasTyroller  10 หลายเดือนก่อน +9

      That's a useful addition. Good to know.

    • @chocolate_maned_wolf
      @chocolate_maned_wolf 9 หลายเดือนก่อน +1

      @@JonasTyrollerthis comment should be pinned tbh

  • @charlesmayberry2825
    @charlesmayberry2825 5 หลายเดือนก่อน +2

    I'm glad you pointed out the issues with update and fixed update, The thing is, some things need to be calculated before you should continue, in which case, fixed update is the answer, however those need to be lightweight because you need them for function quickly, in some games the physics may not need high accuracy, in which case, it's fine for them to happen whenever. However games that are heavily reliant on the physics (like an FPS) you really need those collisions calculated before continuing.

  • @runrajrun
    @runrajrun 10 หลายเดือนก่อน

    Really entertaining video, the pacing is great! I'd love move videos like this in the future

  • @RobLang
    @RobLang 10 หลายเดือนก่อน +54

    *screams in multiplayer*
    Love this video, Jonas. Beautifully explained. Would love to see more like it!

    • @magnusm4
      @magnusm4 10 หลายเดือนก่อน +4

      Please elaborate. I've wanted to implement multiplayer in the future so any hiccups or things to consider is really useful.

    • @aleksapetrovic7088
      @aleksapetrovic7088 10 หลายเดือนก่อน

      .

    • @IONProd
      @IONProd 10 หลายเดือนก่อน +3

      @@magnusm4 multiplayer you can't just use deltatime for each pc because everything needs to be synced. So you need a main computer (which could be a player too) that does the calculations, and the players' pcs need to display that information. But frames can't be involved in the calculations of the variables, otherwise things would move really weirdly. You need the numbers sent to the pcs, and the pcs to render that information using deltatime, because you need to get the correct number for that point of time based on when the individual player's frame renders. And the rendering calculations are gonna need to be precise otherwise objects are going to appear in the wrong spot because if the calculation is off the number on the server is still correct, but it's displayed incorrectly on the player pc.

    • @Kenjuudo
      @Kenjuudo 8 หลายเดือนก่อน +1

      ​@@IONProdAnd this is the reason why so many beautiful indy games lack multiplayer support. It's really hard to do properly.

  • @cyzaine
    @cyzaine 10 หลายเดือนก่อน +169

    As a Godot user, I love that this just explains the concepts. Doesn't matter what the engine is! I felt I kinda knew all this, but it's presented so well I feel I learned something anyway.

    • @lukkkasz323
      @lukkkasz323 10 หลายเดือนก่อน +21

      yeah, btw for those that don't know, the equivalent of FixedUpdate() in Godot is _physics_process().

    • @DevDoge_
      @DevDoge_ 10 หลายเดือนก่อน +10

      ​@@lukkkasz323isnt it _physics_process(Delta)

    • @nobody.of.importance
      @nobody.of.importance 10 หลายเดือนก่อน +7

      Yeah, thankfully stuff like this is pretty engine agnostic. Once you know how one engine works, a lot of it is easy to carry over to others, at least from a technical perspective.

    • @anyapeanutlover
      @anyapeanutlover 10 หลายเดือนก่อน +2

      I'm also a Godot user, and I know that Update() is "_process(delta)", and FixedUpdate() is "_physics_process(delta)"

    • @RADkate
      @RADkate 10 หลายเดือนก่อน +1

      ive also never seen someone mult everything by delta time in a godot tutorial

  • @legendgames128
    @legendgames128 6 หลายเดือนก่อน +4

    2:20 Well, arguably, Betty has the advantage here, because as she and Jerry go really far distances, Jerry is changing his x position by a very small number, which gets essentially zeroed out as he loses precision, meanwhile, Betty can keep going for a bit longer, since she is adding a bigger number to her x position, thus precision takes longer to catch up with her.

  • @RyanCamaratta
    @RyanCamaratta 4 หลายเดือนก่อน

    Subscribed, i really like your fun way of explaining things
    Most people try this and imo wind up compromising the quality of the video/explanation/etc but not here, this was great!

  • @lucaheft
    @lucaheft 10 หลายเดือนก่อน +4

    I dont think your right with the assumption that deltaTime lags behind 1 frame. Unity docs also state, that it's "The interval in seconds from the last frame to the current one".
    So it's basically the time since last frame to the start of calculation of the current frame.
    I briefly tested by logging Time.deltaTime ,Time.time and Time.frameCount. If you press Play in "Paused" mode you can see for the first frame the deltaTime is 0 but for the second frame you will get the correct deltaTime. If the deltaTime would be delayed by 1 frame you should see 0 for the first two frames. As there is nothing to compare against.
    Interestingly Unity seems to be buggy in regards to the deltaTime. If you don't start with Pause enabled, you somehow get a deltaTime > 0 in the first frame. Also if you do start in Paused Mode but disable it after stepping a few frames. You will somehow get a deltaTime of 0 at the frame you disabled paused mode ¯\_(ツ)_/¯

    • @APaleDot
      @APaleDot 10 หลายเดือนก่อน

      I think this is an ambiguity with the phrase "current frame". In the video, he means the frame that hasn't been displayed yet, and the "start" of that frame is when it is displayed. But most game developers think about the "start" of the "current frame" as when the previous frame ended and the frame is displayed at the "end" of the frame rather than the "start".

  • @JonasTyroller
    @JonasTyroller  10 หลายเดือนก่อน +18

    Which grade did you get? :D

    • @Alithegamer99
      @Alithegamer99 10 หลายเดือนก่อน +1

      Please when is thronefall dropping on PS4

    • @ngoclangthi7442
      @ngoclangthi7442 10 หลายเดือนก่อน +1

      I got grade c! (Being a beginner programmer that can't even make a simple player movement script lol)

    • @jpratt8676
      @jpratt8676 10 หลายเดือนก่อน

      F, because I didn't write down my points. I did okay but it counts for nothing :P

    • @Pixel-fish
      @Pixel-fish 10 หลายเดือนก่อน

      F i got 10 in the second question and ten in another and then lost ten

    • @veritas7010
      @veritas7010 8 หลายเดือนก่อน +1

      Grades are of no importance

  • @MagicGonads
    @MagicGonads 10 หลายเดือนก่อน +1

    in a networked example you can sync the different perspectives of the world on a fixed interval, but let them use quick approximates in between those fixed intervals (called prediction) so the error has limited time to accumulate into noticeable differences (but also interpolate between the predicted view and the corrected view to avoid jerky motion). (this also applies to rendering done on Update that relies on physics done in FixedUpdate)

    • @gabrielandy9272
      @gabrielandy9272 10 หลายเดือนก่อน +1

      many games use this, killing floor 2, the enemys keep doing repeating the last action so if its walking forwward and lest say the internet goes down, for 4 seconds, it will keep walking forwards for this 4 seconds while its down (u can lag switch test this) when internet resumes they will smothly move to the correct position, terraria does this as well and many other games i know does this, these two games use prediction and interpolation,.

  • @feha92
    @feha92 10 หลายเดือนก่อน +1

    Regarding the lerp code, it is the only one I got 'wrong'... except I got an _entirely_ different answer from either of your possible answers.
    First of all, your function doesn't reach half blend at 1 second, 3/4 at 2, 1-1/8 at 3, 1-1/16 at 4, and so on, instead it is closer to blend=0.5^(0.5*1)=0.7 at 1 second (which btw is much like sin((pi/2)*0.5*1); though that changes as t drifts away from 1, and if t becomes too large or negative it will obviously do sin stuff. Just a fun coincidence and little else). Had your lerpSpeed been set to 1, it should've worked...
    My solution was instead blend = 1 - ls/t, for t >= 1. And either a conditional to handle t 1 - ls/(dt+ls)
    const g = dt => 1 - 0.5**(ls*dt)
    const test = func => dts => dts.reduce( (acc, dt) => lerp(acc, 1, func(dt)) , 0)
    // ie. test(f)(dts) or test(g)(dts)```
    dts is an array of deltatimes. For some reason f differs depending on which array is used, even when sum(dts) is constant (ie. at the second second f should give 0.8. but dts's ` [0, 1, 1]` gives 0.88..9 while `[0, 2]` gives the correct 0.8. g meanwhile works correctly, even if it seems to have some floating point inaccuracies (so worthwhile to ie. set precision at 3 decimals).
    Any ideas why the exponential g worked, but the non-exponential f didn't?
    So in total, I'll give you a -30 point penalty (so you only got 20 points) for using a non-intuitive shape to your graph (humans can't calculate), and I'll put mine at +10, since my answer was in reality the ugly hack that's as incorrect as yours (mine's shape is right, but phase is wrong, as opposed to yours's that has wrong shape, but right phase), and only deserves as few points as yours _even if it had worked,_ which it didn't and thus I deducted 10 points extra from mine.
    (although I _should_ rightly deduct a couple extra points from you for using the magic number 0.5f as the base, with no explanation why - any number 0

  • @cptshini
    @cptshini 10 หลายเดือนก่อน +3

    Hey Jonas. I must admit that I almost wrote a slightly angry comment claming your answer, to the lerp() function example, was incorrect. However, while writing the comment, I realized you actually wrote the function as the following:
    current = Lerp(current, finish, t);
    Instead of what I thought you wrote, and based my answer off:
    current = Lerp(start, finish, t);
    So yeah... I think your way is a strange way to do it, and also causes some confusion in regards to the question you asked; at least it did for me. I would've gotten a B instead of a C if I didn't misread :')
    nice vids btw

    • @drdca8263
      @drdca8263 10 หลายเดือนก่อน +1

      Ohhh i also missed that!
      I need to go edit my comment now

  • @routeone4790
    @routeone4790 10 หลายเดือนก่อน +84

    This needs to be turned into a series to help new people to understand more on coding.

    • @battalll
      @battalll 9 หลายเดือนก่อน +5

      i dont think this has to do anything with coding. more like high school physics and how delta time on game engines work with a very very simple explanation.

    • @afriendlyfox
      @afriendlyfox 8 หลายเดือนก่อน +4

      @@Fix-- Why did you get scared away? If you didn't understand anything, I want to say that it's completely normal for a newbie to not understand like 70% of the video. To be able to take something from this video, you need to have basic knowledge of C# (at least be able to write a quadratic equation solver), basic knowledge of Unity (at least what GameObject is, what MonoBehaviour class and its methods are and a rough idea of how physics work in Unity), a good school level math and some calculus knowledge. Besides, you have to have tried to make a character move to encounter the problems Jonas is talking about.

  • @descai10
    @descai10 10 หลายเดือนก่อน +4

    19:50 I generally find it better to just use deltaTime alone as the exponent rather than multiplying by a lerp speed. This way you can adjust the 0.5 to whatever ratio you want the lerp to reach each second.

  • @JustinBieshaar
    @JustinBieshaar 10 หลายเดือนก่อน +1

    This was truly such a treat to watch! As an experienced game developer myself, I am definitely sharing this with aspiring and junior devs around me as this is such an informative and fun way to understand the use of deltaTime. Big ups and don't mind making more of these videos! 😉

  • @ThiagoJaqueta
    @ThiagoJaqueta 10 หลายเดือนก่อน +9

    The reason why fixedDeltaTime exists, is that you'll be able to change the rate of fixed updates per second. By default unity uses 50hz, but you might wanna increase or decrease this value depending on your project. If you don't multiply your values by the delta, changing the rate in [Edit > Settings > Time > Fixed Timestep] will result in the physics running faster or slower than intended.

    • @Pixelhurricane
      @Pixelhurricane 10 หลายเดือนก่อน

      yep absolutely, once was having issues with the precision of physics collisions in a project I was working on so I had to bump up the fixed update rate to help solve it. I use fixedDeltaTime in my workflow for exactly cases like that, I might have had to rewrite weeks of code otherwise

    • @rhysvanderwaerden5518
      @rhysvanderwaerden5518 10 หลายเดือนก่อน

      You can even modify fixedDeltaTime at runtime.

  • @L1Q
    @L1Q 10 หลายเดือนก่อน +3

    I expected a tip related to doing visual calculations exactly at render time by accounting for extrapolation in the shader. Game logic can still run 100% correct and lag by a frame, but image is always as fresh as it can possibly be. Great use for this is e.g. rotating camera with mouse/joystick movement. Another approach could be to use absolute time. Absolute is way better for most functions that can have a definite starting point. The last task is such a case. No way accumulate error over time. Just subtract start time from current time and plug the function result into lerp. And for bonus points: do both in the shader :D

  • @richardericlope3341
    @richardericlope3341 10 หลายเดือนก่อน

    Awesome vid!
    I've always been partial to fixed timestep. It's just a few vars and a singgle function you call everyframe. Less calculations as well when compared to variable timesteps.
    Slowdowns are better than frame jumps. Collisions get crazy unless you do some swept tests in variable timesteps.
    Online games though is where variable timesteps shine.
    I once made an article about it that shows how to use variable, fixed, fixed + accumulator(Gaffer's technique) , etc. alongside each other.
    Seeing them simultaneously run was nice.

  • @LePeppino
    @LePeppino 10 หลายเดือนก่อน

    That was great! As a newbie in game dev I was really proud to get some questions right, hehe. And your examples and explanations were really good and useful, would love to see more like this. Subbed!

  • @skatehansen
    @skatehansen 10 หลายเดือนก่อน +9

    Thank you ! currently developing my first game now, and want speedrunning as a focus. So I'm always scared of having inconsistent results. I mostly do FixedUpdate stuff tho. Rb char controller. But anyone know any other areas I should look out for or ways to test this easy ? the lag spike was a neat trick. Edit: oh no, im actually doing all the speed calculation in Update, time to refactor some stuff... haha

  • @simaopereira9416
    @simaopereira9416 10 หลายเดือนก่อน +4

    Wow, I'm honestly quite impressed by the quality of this video. It's very entertaining and informative at the same time, I hope you do more videos like this ;)

  • @emiroguy
    @emiroguy 10 หลายเดือนก่อน

    Cool video, good explanations with good humor! I just subbed, looking forward to watching your other videos!

  • @KillerQ13
    @KillerQ13 10 หลายเดือนก่อน

    I'd like to bring up a point not covered. Simple things like menus or not particularly graphically intense games going as fast as possible can absolutely decimate the GPU. There is no good reason for a menu to be rendering at 3000FPS while the player wonders why the room suddenly got so hot. Even worse, this doesn't play nice with OBS game capture. The capture hook will try to grab every single one of those 3000 frames and it doesn't go well. I can't count how many times I've seen a streamer capture a game and suddenly their whole stream becomes a laggy mess. Their first response is usually to turn down the graphics settings which can inadvertently make the situation even worse. Smart ones know to enable a frame limiter or hope VSync has a proper frame limiter but for most this seems counterintuitive ("I have bad frames, so why would I lower them?"). Some kind of frame limiter should be on by default with some option to adjust/turn it off.

  • @sealsharp
    @sealsharp 10 หลายเดือนก่อน +5

    A little technical precision in times of "with AI everyone can make games without learning or hard work". Wonderful.

  • @deltapi8859
    @deltapi8859 10 หลายเดือนก่อน +3

    "betty is lacking behind, what have you done, you monster" ... beautiful... The whole concept. Beautifully done.

  • @seanthesheep
    @seanthesheep 10 หลายเดือนก่อน

    I'm not a game dev, but I sometimes make animations for the web, and I come from Scratch, where everything runs at a fixed 30 FPS.
    But on the web, requestAnimationFrame (seems to be like Unity update) uses your monitor's refresh rate, so I have to take into account variable frame rate (like deltaTime). I wanted to use the following idioms in Scratch for animations:
    // gravity
    set y to (10)
    set [yv v] to [0]
    forever
    change [yv v] by (-0.5)
    change y by (yv)
    end
    // gradual approach (like exponential decay)
    forever
    change x by (((target x) - (x position)) * (0.8))
    end
    But I didn't know how to make them work with variable frame rates, so I ended up just implementing my own fixedUpdate. So this video is quite enlightening on how I can do it without fixedUpdate

  • @junaidywijaya6413
    @junaidywijaya6413 8 หลายเดือนก่อน

    I think this is a very interesting topic because i also always use approximations because who plays games with 2 fps, but yeah it's informative nonetheless, and also for the lerp one, if you use linear lerp instead of exponential lerp can we use the same formula to calculate the time?

  • @Strong256
    @Strong256 9 หลายเดือนก่อน +4

    Mans violated my last braincell after clapping for nobody at 12:50

  • @SpaceMushroomAdventures
    @SpaceMushroomAdventures 10 หลายเดือนก่อน +9

    The amount of work put into this video is insane! I am not even interested in deltaTime, but I am still watching

  • @bluefake_or_smt
    @bluefake_or_smt 10 หลายเดือนก่อน +2

    19:27 I had as a solution:
    float elapsedTime;
    void Update() {
    elapsedTime += Time.deltaTime * someMul;
    transform.position = Mathf.Lerp(startPos, target, 1 - 1 / elapsedTime);
    }
    I was hela confused when you presented your solution, but then saw you used transform.position instead of startPos. It would work if the startPos is set, but your solution doesn't need that and is therefore still better
    Edit: Looking back I see the issue that you should probably split the Time.deltaTime-adding in 2 halfs

    • @Spelo1
      @Spelo1 10 หลายเดือนก่อน

      Same thing, was hella confused when he didn't put in a time counter until I've noticed that the start position is not a constant one

  • @victordrouinviallard1700
    @victordrouinviallard1700 10 หลายเดือนก่อน

    3:50
    - (d) can be valid in some engines (ex: in some ECS engines one can calculate a different dt for each (group of) system based on when they started last time; this can be useful for some systems that don't run every frames but still need to know when they were last updated, although in that case they can also be held responsible for just adding up what the engine tell them dt is even when they don't process anything else)
    - (a) and (b) are missing info : what is "the time of the last frame" -> you should specify if you are talking about the time the frame was done rendering or when the frame (not just rendering, also simulation, physics, etc.) started. You seem to be talking about when the frame was done rendering (and likely assume this is what is done last?) but the ambiguity of the question is why b) also makes sense (the time elapsed between the _beginning of_ the frame currently being processed and the _beginning of_ the one preceding it)

    • @victordrouinviallard1700
      @victordrouinviallard1700 10 หลายเดือนก่อน

      13:30
      That trick, although it works to prevent framerate impacting speed/acceleration, also isn't the proper solution in many cases. I believe you understand that already, but viewers be aware: don't use this approximation for things like vehicles or rockets which often have non-constant accelerations (vehicles will accelerate slower as they go faster, and rocket may accelerate faster as they lose weight and leave draggin atmosphere).

  • @RevenaSurniak
    @RevenaSurniak 7 หลายเดือนก่อน +4

    just when you think it starts to make sense

  • @1e1001
    @1e1001 10 หลายเดือนก่อน +3

    i've tried to make my own game engine before :), 155/160,
    here are my notes / answers: anything in [square brackets] i added after seeing the answer in the video
    1. `position.x += Time.deltaTime * this.playerSpeed` since you're in `Update` (maybe add a cap on `deltaTime` to prevent intentional lag from breaking your game)
    2. b (time between start of current frame processing and start of previous frame processing) [i'm counting this as +15 since end of a frame is pretty much start of the next frame (actually start of frame is better because if you present way earlier then v-sync will add a delay of it's own which can mess things up)]
    3. small shift over, since the game is still presenting the same next frame [like the frame it's processing is the same as the frame that lagged]
    4. replace `deltaTime` with `fixedDeltaTime`
    5. `var oldSpeed = this.playerSpeed; this.playerSpeed += Time.deltaTime * this.playerAcceleration; position.x += Time.deltaTime * (oldSpeed + this.playerSpeed) / 2` integration my beloved [this is equivalent to splitting the update in half]
    6. setting speed = to 10 instead of +=ing 10??
    7. thinking about this one mathamatically
    - lets say a speed of 1 means you get from 0 to halfway in 1 second
    - 1s dt = 0.5 lerp
    - 0.5s dt = some lerp x such that 1 - (1 - x)^2 = 0.5
    - ys dt = some lerp x such that 1 - (1 - x)^1/y = 0.5
    - solve for x & simplify: 1 - 0.5^y
    - `transform.position = Vector3.Lerp(transform.position, targetPosition, 1.0 - 0.5 ** (Time.deltaTime * lerpSpeed))` or however c# does exponents

  • @xijnin
    @xijnin 7 หลายเดือนก่อน +1

    Well, in gamemaker it's very rare to use delta_time, but when we make a timer we use room_speed, which is the gamespeed, like
    my_time = 5 * room_speed;
    So my_time will be 5 seconds

  • @MarissaFarmer
    @MarissaFarmer 10 หลายเดือนก่อน

    This was a really great video. I don't see a lot of in-depth discussions to this detail, so I really liked it. I hope you do more!

  • @louisdalibard818
    @louisdalibard818 10 หลายเดือนก่อน +5

    Great video! However, wouldn't 19:49 still be wrong though since you are just using the deltatime for each frame and not a sum of all previous deltatimes?

    • @MichaelDarrow-tr1mn
      @MichaelDarrow-tr1mn 3 หลายเดือนก่อน

      The lerp is from the current position, not the starting position.

  • @wareya
    @wareya 10 หลายเดือนก่อน +4

    Very good!!! I'm glad it's getting easier and easier to teach people about the acceleration gotcha. I'm always sad when I play a precision platformer and some of the jumps are impossible unless I limit the game to 60fps.
    I got 160 points!

    • @dexlovesgames_dlg
      @dexlovesgames_dlg 10 หลายเดือนก่อน

      Hey you seem to understand this. can you explain why he used .5f as if it means half? isn't that hexadecimal for 95? isn't he trying to get half the acceleration for the first part of the frame and half the acceleration for the second half of the frame? if that's the case why didn't he actually just use .5?
      And if he wasn't trying to get half, doesn't that mean the snails would've accelerated quicker than they were when it was just one line? was the point not to get them to move the same speed but split the acceleration addition up so that it would get an average of the frame start and the frame end acceleration?
      to be clear, i need no explanation of delta, i understand how it works. I just don't get this bit. about splitting the acceleration into two. i get why he does it, cuz i understand why you wouldn't want the acceleration from before nor the after, but rather the midpoint of the two, i just don't understand how multiplying by .5f gets that, unless .5f is in fact just .5, but it seems like it's hexadecimal for 95
      edit: oh my god, i was right the whole time it is just 1/2. 0.5f is unity notation for floats. that was so confusing as someone who uses godot. correct me if i'm wrong

    • @wareya
      @wareya 10 หลายเดือนก่อน

      @@dexlovesgames_dlg yeah, f is the suffix for "this is a single-precision float, not a double-precision one"

  • @simoncodrington
    @simoncodrington 10 หลายเดือนก่อน

    Outstanding video mate, great work trying to demystify this. Be keen to see more content like this

  • @benhur2806
    @benhur2806 10 หลายเดือนก่อน +1

    Funnily enough the case where you do a half step before and after is a better approximation in any case, as that corresponds to the midpoint RK2 method.
    What also works for that case, and is also a valid RK2 method, is computing the average of both the speed at the start of the step and at the end of the step.
    And of course there's even fancier methods like RK4:
    (I will refer to the speed at the start as v0 for clarity)
    Make one step with 1/2*deltaTime, store the speed resulting from that step in v1
    Make one step from the starting position with v1, also 1/2*deltaTime, store the speed after that step as v2.
    Then do one step, again from the start, this time with full deltaTime, using v2 and store the speed after that step as v3.
    Now take a weighted average of 1/6 * v0 + 1/3 * v1 + 1/3 * v2 + 1/6* v3, lets call this result v, and then using this final v do the last step, yes, again from the start, with deltaTime. The resulting position will be your now even better approximation!
    Is this horribly overkill for most games? Of course! But I'd be remiss not to mention it. :P

  • @TheShelfman
    @TheShelfman 10 หลายเดือนก่อน +19

    Thank you for your service professor Jonas😎

  • @sixtenhugosson
    @sixtenhugosson 10 หลายเดือนก่อน +12

    During the part on acceleration, you can use the equations of motion to get:
    transfrom.position += Vector.right*speed*dt+Vector.right*acceleration*dt*dt/2;
    speed += acceleration*dt;
    You should get the same result but in a "physically correct" manner. In the end it reduces to the same result, but it could still be useful.

    • @EfeDursun125
      @EfeDursun125 10 หลายเดือนก่อน +1

      use * 0.5f

    • @mrnowhere-sc3mv
      @mrnowhere-sc3mv 10 หลายเดือนก่อน +3

      Correct me if I'm wrong, but the first method (which is the same as you provide) is called the forward Euler method, which tends to artificially adds energy to the system the further it goes. Updating speed before position (the sympletic/semi-implicit Euler method) or adding half before and after (the midpoint method, which equates to 0.5 because he is using a linear function) tends to be more stable (the error is bounded)

    • @hardtofinduniquename
      @hardtofinduniquename 10 หลายเดือนก่อน +1

      To be clear: It's not just the same result but it's also the same mathematical formula, except not applied with intermediate state (only modify speed once).
      It's easier to see if you simplify the formula to:
      transform.position += Vector.right * dt * (speed + acceleration * dt/2);
      speed += acceleration * dt;
      And then pulling out the acceleration term to apply to speed makes looks like Jonas' code:
      var boost = acceleration * dt/2;
      speed += boost;
      transform.position += Vector.right * dt * speed;
      speed += boost;

    • @hardtofinduniquename
      @hardtofinduniquename 10 หลายเดือนก่อน

      ​@@mrnowhere-sc3mvFor anyone who wants to go deeper on this math, "Math for Game Programmers: Building a Better Jump" goes into Euler integration, Velocity Verlet, and concludes simplified Verlet (the same result we have here) is a good compromise: th-cam.com/video/hG9SzQxaCm8/w-d-xo.html

  • @rightwingsafetysquad9872
    @rightwingsafetysquad9872 10 หลายเดือนก่อน +1

    Using the mid point to calculate the average on an exponential function should be sufficiently accurate unless your frame time is extremely large. I do it for IRL ballistics calculations with an assumed time interval

  • @gdmathguy
    @gdmathguy 10 หลายเดือนก่อน +2

    12:07 Idk man this seems like a fun thing you would solve by integrals.
    Since speed s is increasing by acceleration a times the time t passed, we can do this function:
    f(t)=a*t=s
    Since the integral function, which calculates the area under a curve, is the reverse of the derivative, we just need to add 1 to the power of t and also divide by 1 plus the power of t:
    Integral(a*t)=(a*t²)/2
    To get the area from 2 different points, you just need to do that calculation with the time that's passed (t) plus deltaTime (dt) and then you need to subtract the result of putting only t into that new function from the result of t+dt. It could look smth like this:
    (a*(t+dt)²)/2-(a*t²)
    Edit: Spoke too soon but hey, at least this was a cool solution

  • @Serlith
    @Serlith 10 หลายเดือนก่อน +3

    This lerp thing called "thecorrect way to lerp" is misleading, because in lerp we are LINEARLY interpolating, and you have showed us an easing function. Which is fine, but... Well, not what lerp is about. I'd use Vector3.SmoothDamp for that.
    Usually the "correct" way to use Lerp is to have a defined constant start value and an end value and calculate the t parameter by incrementing time elapsed and dividing it by the lerp duration (precalculated from speed and distance or w/e), instead of submitting the current value as the first Lerp argument for every frame.
    Then you can get fancy and add easing functions to that t param calculation.

    • @EpicGamerScout
      @EpicGamerScout 10 หลายเดือนก่อน

      I don't think there's necessarily anything wrong with using a lerp in this way. As long as you're careful to acknowledge that you're using the lerp as a building block for your own primitive exponential easing function, and make sure to do it right, then that's probably one of the simpler and more transparent ways to think about implementing one.
      "I want the distance to half every X time" > "Lerp is an extremely simple way to get the halfway point" > "Here's how I can modify the lerp implementation to be robust to changing update rates". You might be reinventing the wheel a bit, but if you're more familiar with the math than the engine, it works out just fine!

    • @Serlith
      @Serlith 10 หลายเดือนก่อน

      @@EpicGamerScout It has the distinct issue of having to snap the object to target position after the elapsed time, leaving us with about the same amount of code though.

  • @TacoTechnica
    @TacoTechnica 10 หลายเดือนก่อน +12

    Loved this, a lot to chew on even for more experienced game devs! Just one extra thing, in 15:35 isn't there also a potential error where the jump input is checked after running movement code, introducing an extra frame of delay when a user wishes to jump?

  • @astecheee1519
    @astecheee1519 9 หลายเดือนก่อน

    Loved the video! As far as functions that approach but don't quite reach 1, there are other options available, yes? I feel like hyperbola could be useful.

  • @sosasees
    @sosasees 10 หลายเดือนก่อน +1

    these are my answers (in GDScript)
    and how many points i got from each:
    1. (+10) ˋˋˋposition.x += run_speed * deltaˋˋˋ
    2. (+20) time between the last frame and the one preceding it
    3. (0) Berry will move as much as he would have if the frames did render
    4. (0) we don't need to change the FixedUpdate code
    (Godot does not have fixed_delta, so no points for Godot users)
    5. (+20) ˋˋˋ
    extends Node2D
    @export var acceleration := 1.0
    var velocity := 0.0
    func _physics_process(delta):
    velocity.x += acceleration * delta
    position.x += velocity * delta
    ˋˋˋ
    6. (+10) ❔️
    7. (0) ˋˋˋ
    extends Node2D
    @export var target_position := 64.0
    var lerp_speed := 0.5
    func _process(delta):
    position.x = lerp(
    position.x, target_position,
    lerp_speed * delta
    )
    ˋˋˋ
    70 points total, grade C

  • @MythicLegionDev
    @MythicLegionDev 10 หลายเดือนก่อน +6

    Thank you for this cursed knowledge Jonas

    • @muzzaclips768
      @muzzaclips768 9 หลายเดือนก่อน

      We thought you perished!

  • @allenhalsted4895
    @allenhalsted4895 10 หลายเดือนก่อน +33

    I have been developing games since the 1980s and have built several game engines from scratch. So I didn't really learn anything today, but I think that Jonas did an excellent job of explaining the concept. Keep up the good work!

  • @BluesM18A1
    @BluesM18A1 10 หลายเดือนก่อน +1

    My solution to deltatime inconsistencies was always "just make sure the game runs at full framerate even on potato computers lmao" but even so, looks like I still have a lot of things to check for and improve in my code when one of the games I'm making is about all about speed and precision with the physics engine.
    I know someone will try to run the game on a computer that's probably weaker than my already 10 year old test machine, and they'll be counting on it.

  • @thalianero1071
    @thalianero1071 7 หลายเดือนก่อน

    This reminds me of Minecraft entity rendering, where the partialTicks / tickDelta parameter which appears to be this but measured in server ticks instead of seconds. MCP mappings (partialTicks) appears to think this is the fraction of the current tick you’re rendering at, while Yarn (tickDelta) appears to think this is the tick distance between the previous two frames.
    For actually writing entity rendering code, either interpretation works

  • @rayank2010
    @rayank2010 10 หลายเดือนก่อน +4

    when your use the lerp function your supposed to have a "linear" speed without acceleration because it's a Linear intERPolation, if it looks exponential it's because you change each frame the beginning position (parameter a)
    so :
    pos = lerp(pos_begin, pos_end, t)
    Great video though !!

    • @pepperdayjackpac4521
      @pepperdayjackpac4521 9 หลายเดือนก่อน

      So, is the reason the lerp was looking exponential causes by the fact he use transform.Position, which got the current position, instead of the start position which never changes, so it should be a constant, somewhere outside the update function?

    • @rayank2010
      @rayank2010 9 หลายเดือนก่อน

      @@pepperdayjackpac4521
      Yes it wouldn't be exponential if he sets the initial position.
      You can test yourself to see.

  • @_stephenhubbard
    @_stephenhubbard 10 หลายเดือนก่อน +5

    TH-cam game dev eduction needs more videos just like this! Really great format.

  • @YVZSTUDIOS
    @YVZSTUDIOS 8 หลายเดือนก่อน

    that was well explained, but what if I want to for example move an object from one pos to a target pos smoothly? Start slow, go fast and then slow again and arrive at target pos?

  • @SauROnmiKE
    @SauROnmiKE หลายเดือนก่อน

    This video was recommended to me at 1AM in bed, stayed glued to my phone screen all of the time and still understood everything. World-class explanation.
    Subscribed

  • @DaMu24
    @DaMu24 10 หลายเดือนก่อน +20

    I highly appreciate the math explanations. Calculus is an important topic that can be learned as early as high school, maybe earlier if you have the perfect teacher, and solutions to game development like this are why learning advanced math is important.

    • @zeckma
      @zeckma 6 หลายเดือนก่อน +1

      The sad thing is that teachers make a terrible case for learning calculus, algebra, and geometry, usually throwing only rocket science as an example. I went through the classes just fine but never understood why I should learn the material and could never discover a legit use case for it. That is until dealing with graphics and games, at which point I heavily regretted forgetting most of what I had learned.

    • @JanTGTX
      @JanTGTX 4 หลายเดือนก่อน

      I'm with you, but schools don't seem to have an interest in teaching "real" math. It's all just about calculating numbers, like robots.
      Studying physics was an absolute eye opener for me. There I got taught math on a more fundamental level, which really made it click. I'm still wondering why they don't teach axiomatic systems, logic and set theory in schools and let the students be creative for once. The basics actually aren't that hard.
      After having achieved some knowledge of those topics, calculating stuff, even derivatives and integrals, which are the highest level topics in schools, becomes piss easy.

  • @thecryptacoder1126
    @thecryptacoder1126 10 หลายเดือนก่อน +4

    It says 0-10 for an F, what happens if I got a -10?

    • @GrifGrey
      @GrifGrey 10 หลายเดือนก่อน

      give up
      (just kidding, keep on learning)

  • @StephenCunliffe
    @StephenCunliffe 10 หลายเดือนก่อน

    @JonasTyroller - great content, I appreciated the math and the demos... but how many points do we score for noticing your shirt was on backwards? 🙂

  • @Ilandria.
    @Ilandria. 7 หลายเดือนก่อน

    Update loop frame time being used in fixed/physics update and impulse/instantaneous effects are the two that I run into the most often when looking through other people's code. Blindly writing something like position.x = Lerp(a, b, deltaTime) is probably the next most common thing I encounter.

  • @JeanPhilippeBoucher
    @JeanPhilippeBoucher 10 หลายเดือนก่อน +5

    Jokes on you, I multiplied my grade by delta time and now I'm above the maximum!

    • @lFunGuyl
      @lFunGuyl 14 วันที่ผ่านมา +1

      Jokes on *you*! You multiplied your grade by a number almost certainly less than one! Your grade was lowered to a fraction of what it would've been!
      Unless you run with less than 1 FPS in which case the joke would again be on Jonas...

    • @JeanPhilippeBoucher
      @JeanPhilippeBoucher 14 วันที่ผ่านมา +1

      @@lFunGuyl I'll take the risk for a shot at glory!

  • @TagaRamer
    @TagaRamer 10 หลายเดือนก่อน +3

    I have a degree in electrical engineering and I changed my career into programming and finally the math I learned became useful! I loved your video !

  • @bastian_5975
    @bastian_5975 10 หลายเดือนก่อน

    I might be missing something because I am on more than 24 hours without sleep, but assuming I am not:
    For the last snail lt would be an inverse inverted function, so you could also do 1-1/(lerpSpeed*deltaTime+1) and achieve the same effect, except if you want mathematical perfection, you would actually want the same graph over time, which would instead mean that you should instead create variables for starting position and time since you started lerping (either by simply adding together deltaTime or by keeping a starting time stored and then subtracting current time) and then do
    transform.position = vector3.Lerp(startPosition, targetPosition, 1-1/(lerpTime*lerpSpeed+1))
    because you're asking for a function with a limit of 1 as x approaches infinity that will give the same result for any given value of x, and with the approximation that directly references deltaTime you are actually using multiple separate functions that change depending on deltaTime. As deltaTime approaches zero, you do end up with a function that I am too tired to derive, but it probably involves e somewhere... I tried to get someone else to explain why your approximation fails at perfection, but I am far too tired at this point to even communicate that much.

  • @JellyMudkip
    @JellyMudkip 10 หลายเดือนก่อน

    Thanks for the video, you help me with the issue in Lerp function hahaha now I can solve it

  • @Firestone-Games
    @Firestone-Games 10 หลายเดือนก่อน +5

    New Jonas Video Lets gooooo!

  • @MiTheMer
    @MiTheMer 10 หลายเดือนก่อน +6

    Please more of this format!! It was helpful and entertaining at the same time!

  • @CSDragon
    @CSDragon 9 หลายเดือนก่อน

    16:20 I thought the thing that was missing was something to stop it from triggering every single frame when held.
    If I'm remembering correctly, Input.GetKeyDown doesn't check if the key is pressed on that frame, it just checks if it's down or not

    • @SimianBastard
      @SimianBastard 6 หลายเดือนก่อน

      Input.GetKeyDown only returns true during that frame. Input.GetKey would trigger every frame.

  • @jonaskoelker
    @jonaskoelker 8 หลายเดือนก่อน

    I'm not a game dev. Not really. Here's what I have thought up myself, based on what others have told me:
    - Run physics and graphics independently. That is, run physics updates at a fixed number of steps per second.
    - For a 1-frame delay between physics and rendering, keep track of when the last two frames happened. Do all the physics updates scheduled for that time interval; no more, no less.
    - When doing a physics update, first find the analytical solution on a whiteboard, then decide whether you can implement that or whether to go for a numerical approximation.
    - Then go do that.
    I guess maybe for less physics-rendering lag, you can keep track of some estimated recent average fps and do an amount of physics updates such that if the current frame duration is average you will end up rendering the most recent physics state, rather than the most recent physics state before the last frame. Maybe you want to put some bounds on that, such that you're never more than N physics steps ahead of the most recently rendered frame.

  • @norude
    @norude 10 หลายเดือนก่อน +4

    What grade do I get for a total of -10 points?

  • @jbaidley
    @jbaidley 10 หลายเดือนก่อน +5

    I disagree with your description of deltaTime, it's not the time between the last frame and the frame before that. It is the time elapsed between the START of the current frame and the START of the last frame. In most cases these mean the same thing, but it's usually implemented as I describe.

    • @JonasTyroller
      @JonasTyroller  10 หลายเดือนก่อน +2

      Ah, I see. Thanks for specifying that further. Should still work as described in the video then, right?

    • @skatehansen
      @skatehansen 10 หลายเดือนก่อน

      way easier to wrap your head around too, thanks

    • @jbaidley
      @jbaidley 10 หลายเดือนก่อน

      @@JonasTyroller Yes, the description of how it works is correct.

    • @lennysmileyface
      @lennysmileyface 10 หลายเดือนก่อน +2

      @@JonasTyroller Yeah you just worded it unintuitively. B could be interpreted as correct because you always set the current time at the start of a frame i.e. the frame that is being processed and the last time at the end (which becomes the start of the previous frame when the next frame starts).

  • @SprocketWatchclock
    @SprocketWatchclock 7 หลายเดือนก่อน

    There's also tween rendering where movement is calculated as a vector and the renderer will render frames as it can with that vector as its guide. Essentially what this does is disconnect the render time from the physics and behavior of the game and can just render frames whatever it wants and the algorithm just moves things linearly as it happens. The advantage is smoother movement regardless of framerate but the downside is it can hurt player response time should an action need to be performed between frames and not just in general. Essentially it does what 3D animation software does, you set key frames and the physics calculation just does it when it wants and the renderer can update the screen ever whenever it wants simply pulling the computed vector and selecting the appropriate distance from it. It's a bit more complicated but it has its use cases where it's ideal. For most games though, movement smoothness isn't as important as rendering quickly to provide feedback to the player. That's not anyways the case so it's nice to just have that in the back pocket for a rainy day or some such thing.

  • @andriib9390
    @andriib9390 10 หลายเดือนก่อน +1

    I think it makes much more sense to use 1-Pow(lerpSpeed, deltaTime) because then it has pretty obvious meaning, lerpSpeed then indicates how much closer we are getting to target each second, for example in case of lerpSpeed 0.5 and deltaTime 2.0 we will get blend = 0.75 which makes sense because we got two times closer each second during last two seconds. Well, then naming it something like lerpFactor will make more sense as well

  • @TackerTacker
    @TackerTacker 10 หลายเดือนก่อน +3

    Great video, I got a 🐝
    Personally I'll stick to the simpler approximated version though, keeps the code simple and more readable.
    If your game is consistently running at ~2 FPS you got bigger problems and if it's just one hiccup it doesn't make a big enough difference IMO.
    At least as long as it isn't an online multiplayer game or something that needs deterministic physics.

    • @MaakaSakuranbo
      @MaakaSakuranbo 10 หลายเดือนก่อน +1

      Make it less simple, stick it into it's own function. There, nice and readable in your normal code

    • @stickguy9109
      @stickguy9109 10 หลายเดือนก่อน

      2fps was just an example. You can have something that accumulates overtime because of wrong deltaTime and gets messed up. For example I had a character controller that would get slower and slower as the frame rate drops and below 15 it would stop moving altogether. See what I mean

    • @TackerTacker
      @TackerTacker 10 หลายเดือนก่อน

      This discussion about the mathematical correct version of lerp is a relatively recent topic in the indie bubble and no one was doing it that way before, without anyone ever noticing a problem, that's how big of a deal it is.
      I don't stop anyone from using the more complex version, I'm just saying that I myself stick to the easy version 🤷

    • @stickguy9109
      @stickguy9109 10 หลายเดือนก่อน

      @@TackerTacker I use a tweening library that takes care of it. But no it has to be correct because it becomes very noticeable when frame rate drops even a little bit

    • @TackerTacker
      @TackerTacker 10 หลายเดือนก่อน

      @@stickguy9109 I think you mean something different than I do.
      By approximate version I mean "lerp( a, b, lerp_speed * delta_time )" not no delta_time at all.

  • @GoodOldQuestion
    @GoodOldQuestion 10 หลายเดือนก่อน +3

    Awesome video! Would be more than happy to see more lessons like this. Quick question, Mr. Jonas:
    16:22
    Do I get 10 points if I did: speed = 10 + Time.deltaTime * acceleration
    (I did so because I wanted order to be: Jump --> Move --> Gravity and not Gravity --> Move --> Jump)

    • @Eschen_
      @Eschen_ 10 หลายเดือนก่อน +1

      The jump in your version still happens after the movement gets applied, meaning it doesn't have any effect in the current frame. The difference in your version is that the jump gets its full power in the next frame instead of being reduced first, but that is only when assuming the deltaTime of the current frame and next frame are equal. If they're not, you're adding some randomness to the jump strength. But really, whether you add this code is just not going to make any perceivable difference (it makes the jump a tiny bit stronger, but you would be tweaking those parameters to get them feeling right anyways), so you shouldn't add it.

    • @GoodOldQuestion
      @GoodOldQuestion 10 หลายเดือนก่อน +2

      @@Eschen_ Thanks for the detailed response!
      You're right! Can't believe I missed that...
      Recap: My goal was to change order to Jump --> Move --> Gravity. It was allowed to change only a single line, so I tried to achieve Jump --> Move --> Gravity order within this limitation (in reality I would just change the lines order). Sadly there is no way to guarantee that deltaTime would be the same for the next frame (aka next time gravity is applied), so the whole thing is pointless -10 points

  • @jakedeschamps4454
    @jakedeschamps4454 9 หลายเดือนก่อน

    This video was great! I had a pretty good understanding of Delta time, and the problems with how it may be used, specifically when the frame rate changes, but I didn't know of any solutions until now! I never considered only adding half of the value calculated by Delta Time, and then the other half after the computation! That's very clever. Before this video, I was working on some algorithm to implement to compensate for the lower precision of lower frame rates, but this looks like it should be sufficient for my needs!

  • @MatthewCoder
    @MatthewCoder 10 หลายเดือนก่อน +10

    You think I'm using delta time incorrectly?
    Well jokes on you, I'm not using it at all.
    If the game lags, everything goes in slow motion and a pop up appears to insult the player's setup

    • @squirrrrrrrrel7483
      @squirrrrrrrrel7483 10 หลายเดือนก่อน +1

      lol

    • @JonasTyroller
      @JonasTyroller  10 หลายเดือนก่อน +3

      Genius solution. We should all start doing it like that!

    • @MatthewCoder
      @MatthewCoder 10 หลายเดือนก่อน

      @@JonasTyroller just finished the video, it was greatly informative and entertaining, thanks Jonas! Sorry about the meme comment hahahaha

  • @ImNotGam
    @ImNotGam 10 หลายเดือนก่อน +3

    4:20 only reason I picked A is because I’ve made my own frame rate controller lol.

    • @kales901
      @kales901 10 หลายเดือนก่อน +1

      i chose d because i thout it made scenes... i already know thats its the ammount of lag