1
\$\begingroup\$

I'm somewhat new to Unity, so I'd like to hear some more experienced thoughts on this. I'm using C# if that helps.

I'm currently working on an arcade game somewhat similar to "Doodle Jump" except, instead of controlling the character, you place platforms to prevent an AI character from falling.

I want to increase the speed of the game over time to make it progressively more difficult for the player. I initially tried just making the camera gradually accelerate upwards, but this made it so the character eventually doesn't fall quickly enough to keep up. Hence, I would like to increase the speed of everything in the level.

My current solution is as follows:

private void AccelerateLevel()
{
    Time.timeScale += timeIncrement;
}

I call this in Update() in the character's movement script.

However, as I understand it, this might not be consistent for different framerates - is that right? Is there a better way of doing this, or is this the best/most consistent way?

\$\endgroup\$
1
  • \$\begingroup\$ Another consistent approach would be by covered distance or platforms. \$\endgroup\$
    – Zibelas
    Commented Nov 18, 2023 at 13:48

1 Answer 1

1
\$\begingroup\$

this might not be consistent for different framerates - is that right?

Time.timeScale is independent of framerate. Unity will continue to try to render at the same framerate regardless of time scale. However, time scale can affect performance and indirectly cause inconsistent behavior affected by framerate:

Increasing the time scale also increases the number of physics updates that must be performed per second of real time, unless you then increase the Time.fixedDeltaTime property. Increasing the fixedDeltaTime will affect the accuracy of the physics and eventually will lead to strange and undesired behavior.

If you have any expensive code which runs at regular intervals, increasing the time scale will make this expensive code run more often. As a simple example:

private IEnumerator UpdatePath() {
    var delay = new WaitForSeconds(.1f);
    while (true) {
        yield return delay;
        // For the sake of example, let's say this function is fairly slow:
        CalculateNewPath();
    }
}

In this example, we calculate a new path every 0.1 seconds of in-game time. At 60fps and the default time scale of 1, that would mean that we calculate the path every 6th frame. Now imagine we set the time scale to 6. Now we'll need to calculate the path every 60th of a second in real time, which means we're now running this expensive function every frame!

This example illustrates another issue - let's say that a player's device doesn't have good performance and can only manage 30fps. This means at a time scale of 1, they would run CalculateNewPath() every 3 frames. At a time scale of 6, they would need to run CalculateNewPath() every half of a frame (since WaitForSeconds() doesn't work like that, the function would still only get called once per frame, now every 0.2 seconds of scaled time)! This type of issue can force you to put all of your game logic into FixedUpdate() functions to ensure the code runs at the correct interval even if the framerate is low.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ I think this answer does a great job at highlighting problems with the proposed approach. I think we're still missing an answer to "what would be the best way" though — do you have tips for implementing the gradually increasing speed mechanic while minimizing these problems? \$\endgroup\$
    – DMGregory
    Commented Nov 22, 2023 at 13:03

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .