playcanvas / engine

JavaScript game engine built on WebGL, WebGPU, WebXR and glTF
https://playcanvas.com
MIT License
9.33k stars 1.32k forks source link

Multiple Delta Time #908

Open marionieto opened 7 years ago

marionieto commented 7 years ago

In games is very common to has multiples Delta Time for multiple purposes:

In PlayCanvas the update method pass the scaled Delta Time (dt) has a parameter. That is perfect, but sometimes we need an unscaled Delta Time.

The problem

  1. Pause game and set scale time in zero. this.app.timeScale = 0;

  2. Pause Menu logic can't use Delta Time to update some elements, because it is in zero. UI.prototype.update = function(dt) { console.log(dt) // log: 0 };

The solution (walkaround)

To resolve the problem I calculate the unscaled Delta Time: this.unscaledDt = (pc.app._time - this.oldTime) / 1000;

How did Unity solve it?

In Unity the update method doesn't pass a Delta Time, it is because the class Time provides multiple Delta Time:

https://docs.unity3d.com/ScriptReference/Time.html

The real solution

I believed it could be a good idea to expose the current Delta Time and an unscaled Delta Time in some instance of the PlayCanvas engine, something like this:

What do you think?

Maksims commented 7 years ago

Here is a classic use case:

Player pauses game, and main game logic is not responding, but menu, and background music, and possibly some other stuff is working as intended. Similar example is inventory system in game, which pauses main game, but continues to use animations in character window, or other things.

Based on just those two examples it is apparent that time scaling is specific for different systems on different level. For example for sounds, it might affect some sound sources, but some not - like button click sound in menu, or music. For animations, it might affect animation in game, but not animation of character in character screen. Particles - same case.

Based on this, the best solution would be if each system would provide a time scaling property that can be applied on different level. For example for audio, this is already possible by changing pitch on individual sound instance, or sound slot, or sound component, or whole sound system. Other systems should expose same mechanics to provide sensible mechanics for all possible time management use cases.

Sound - instance, slot, component, whole system - this is already implemented, and we've used in actual project, and it worked really well with no limits on different cases. Physics - might be challenging, so simply single time scaling factor would be enough. Animation - should have control over individual animations, whole component, and whole animation system. Particles - control per component and for whole system as well.

dt - is a delta time since last frame, and actually if frame rate is 60, then dt should reflect that appropriately, without actually being affected by time scaling. Time scaling is old legacy property that never been used properly within systems and has very limited use cases.

It is best to expose and provide tools to developers to define their mechanics of time scaling, rather than give some workflows that only would cover small % of cases, or require "back-thinking" of "unscaling" timings for explicit things - which is more confusing, than simply being explicit of what should be time scaled.