First I would like to credit NaitorStudios for curve fix, DtRatio idea & Uppernate(BartekB) for the general DeltaTime calculation
Introduction:
Apps are frame based, just like animations the higher the frame rate (FPS), then the faster the animation is, unless you design the animation for a specific FPS
That what most Fusion devs do, they limit the FPS to not go past a point (like: 60 FPS) and design the game to run for that frame rate
While this is perfectly fine, it's not the best thing to do.
For example: If the FPS is capped at 60 and user's monitor is 120 hz, then the extra smoothnes of the display won't be utilized, as there is no in between frames
Another problem: if the FPS got lower than the capped FPS, then the app will run at lower speeds (some kind of unsmooth slow motion effect)
Though these problems won't happen if we used DeltaTime.
What's DeltaTime?:
DeltaTime will make the app run based on the timer instead
It can also alter the game speed how ever you want at any time, so smooth Slow Motion effect will be easier than ever!
DeltaTime calculation:
First create 3 Global Values:
(DeltaTime, OldTimer and DtRatio)
DtRatio: will be used alter the speed timer in ms, as most Fusion games are built on 60 FPS then 16 ms will be the closest ( 60 FPS = 16.6 ms ), You can increase or decrease this value any time to alter the app's speed!
Next we want to actually program the main DeltaTime calculation.
Basic example using DeltaTime:
Here we have an Active object with 2 alt vals(Xpos and Spd)
Instead of just adding Spd to Xpos, we will add (Spd*DeltaTime) to XposAdd (Spd * DeltaTime) to Xpos
So basicaly we multiply a value by DeltaTime if we want it to correspond to timer rules
Now the object moves the same speed on any FPS value!
Solving inconsistant velocity curve:
Above was a basic example utilizing DeltaTime, though if we implemented it in this way for always changing curve movements (like: Gravity addition to velocity) it will unfortunately not work correctly.
So the right way of doing it will be add the gravity addition before AND after Yvel is added to Ypos like this:
- Add Grav * DeltaTime / 2 to Yvel
- Add Yvel to Ypos * DeltaTime to Ypos
- Add Grav * DeltaTime / 2 to Yvel
Now it works as it should on any FPS value!
Very important β (Step checks):
So after we got all this done, we have to consider collision checks too! because if we don't we will have a game breaking bug
So let's say we move 5 pixels, then we are actually skipping 5 pixels (Teleporting) but let's say we move a bit fast like 20 pixels and at the same time the FPS is low
Then the gap will be even bigger! so there are much bigger chance of skipping obstacles now
Note: There are other factors too that can make you skip obstacles, like the obstacle and collider size, and ofc how fast the collider moves, they all are involved into this
That's why we have to use step checks!
Step checks makes the object acually pass the in-between pixels via loops, instead of teleporting
Though passing every pixel is very CPU expensive, as loops are involved into the process, especially when checking for collisions (which is the whole point of doing this in the first place!)
So we have to be careful with it, balancing between quality and speed, So instead of passing and checking every single pixel, we actually just pass a specific amount of pixels
In our situation, as we use DeltaTime, we have to also alter the step checks based on DeltaTime (as don't forget DeltaTime alter's the speed of things based on the FPS and in terms of movement it will skip more or less pixels)
Here is how to do it!:
First create a new Global Value and name it "Quality", it will be used to store the step checks
Then program the Quality calculation:Set Quality to Int(Max(3.0 * DeltaTime, 1))
So this expression does 3 tasks at once:
Setting Quality to 3.0 * DeltaTime (for syncing) Note: 3.0 can be any number, the higher the more checks but also the heavier the game becomes, so every step check matters a lot!
Clamping the quality to the minmum of 1, via the
Max()
exrpresion, which returns the biggest value between the twoConverting the whole calculation in an
Int()
expression , this converts a float value (Number with decimal, like: 1.3) to an Integer (Whole number, like: 3)
Then we alter the code to support both collisions AND step checks
Note: it's very important to divide Yvel by the Quality in the loop (for the loop to not change the actual movement speed of the object)
Another note: The Division by Quality is because the loop is ran "Quality"
number of times
Voila!
And if it was for multiple objects, we just alter the events a bit to use For Each loops:
That's mostly it! just one last thing to consider:
Never multiply by DeltaTime when applying immediate forces!
so this is correct β
:- Set Yvel to -11.0
while this is wrong β:- Set Yvel to ( -11.0 * DeltaTime )
And finaly, thanks for reading! hope it was useful for anyone who wondered about DeltaTime :)
8 comments