3
\$\begingroup\$

I have a game that calculates your score via Time.deltaTime (the more time the more score). On my PC I get about 1200 points if I just idle the game while on my phone I only get about 400 points.

I believe my code must be FPS dependant and that's why my phone is getting a lower score for the same time.

Here's the code:

void Update ()
{
    time += Time.deltaTime;

    score += (int)time;

    timerLabel.text = score.ToString();
}

Sorry if it's something very obvious. I'm quite new at c#.

Can't seem to get the solution to work. It just stays at 0:

Full Code:

    using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using UnityEngine.SceneManagement;

public class EndGame : MonoBehaviour {

    public Text textWin;
    public Text timerLabel;
    public GameObject retryButton;
    public GameObject points;

    private Vector3 offset;
    private float time;
    private float score;


    void OnTriggerEnter (Collider col) {
        if (col.gameObject.name == "Player") {
            setWinText ();
            retryButton.SetActive (true);
            points.SetActive (false);
        }
    }

    void setWinText () {
        textWin.text = "Final score: " + score.ToString();
    }

    void Update ()
    {
        time += Time.deltaTime;
        if (time >= 1.0f) {
            ++score;
            score -= 1.0f;
        }

        timerLabel.text = score.ToString();
    }

}
\$\endgroup\$
5
  • \$\begingroup\$ You should use FixedUpdate for an accurate point measure. \$\endgroup\$
    – z3nth10n
    Commented Aug 25, 2016 at 16:07
  • 1
    \$\begingroup\$ Your code is (a) not resetting "time" when it gets to be above 1.0, and (b) subtracting one from score, not time. This means every time you add one to the score, you immediate subtract one. Score will always be zero. \$\endgroup\$
    – user1430
    Commented Aug 25, 2016 at 16:10
  • 1
    \$\begingroup\$ @Gnemlock there are a few more cases than just Physics. If an outcome depends on how frequently it's evaluated (think of compound interest, and the difference between compounding monthly versus quarterly versus annually) then using FixedUpdate will help get consistent results without special framerate compensating math. The math is straightforward for linear change (x += dx/dt * dt) but for more complicated nonlinear effects this standardised FixedUpdate rate can be a big help. \$\endgroup\$
    – DMGregory
    Commented Aug 25, 2016 at 16:21
  • 1
    \$\begingroup\$ @Gnemlock this is getting a bit off topic, so I'd be happy to discuss further in chat. You're correct that neither method is more accurate for simply tracking or accumulating time. The trick comes when we try to model some particular change over time. If that change is linear we can just multiply the rate of change by Time.deltaTime to keep it consistent as framerate varies. If the change is non-linear then the math can become more complicated. eg. for quadratic growth as in the code above, or things like exponential decay. \$\endgroup\$
    – DMGregory
    Commented Aug 25, 2016 at 23:36
  • \$\begingroup\$ @Gnemlock, not a problem I understand how non-linear could add problems. Cheers =) \$\endgroup\$
    – Gnemlock
    Commented Aug 25, 2016 at 23:45

1 Answer 1

3
\$\begingroup\$

deltaTime is the (or at least, a) correct thing to be basing a time-based score on. It's value does vary with the framerate, of course, since it tracks real-time elapsed time between one frame and the next. On faster frames, it will be a smaller value than on slower frames, but it will always measure real time, so it's basically the thing you want to be using.

How you are using it is wrong, though.

deltaTime is a floating point value, when you cast it to an integer you truncate (drop) the decimal portion of the value. This means that on very fast frames, when deltaTime is less than one, you add zero to the score. On every other frame you add some value to the score, but you're compounding the error more-or-less randomly.

One way to do this which doesn't exhibit this issue is to accumulate delta time until it measures one second, and then add one to the score, resetting the accumulator and preserving the factional part of the number. Something like this, conceptually:

void Update() {
   scoreTimer += Time.deltaTime;
   if (scoreTimer >= 1.0f) {
     int integer = (int)scoreTimer;
     score += integer;
     scoreTimer -= integer;
   }

   // ...
}

This will also make the score counter visually increase at the same fixed rate, instead of as fast as your framerate is.

The cast to int is to extract the whole-number part of the accumulator and add that to the score, and then to subtract that whole-number part out of the accumulator so you preserve the accumulation of fractional time. This helps correct for frames that are extremely slow, in excess of one second long. You could also use Math.Round.

\$\endgroup\$
6
  • \$\begingroup\$ I can't seem to make it work. It just stays at zero. I added the full code. \$\endgroup\$ Commented Aug 25, 2016 at 16:01
  • \$\begingroup\$ @user3078100 you did it wrong. time -= 1.0f, not score \$\endgroup\$
    – Leggy7
    Commented Aug 25, 2016 at 16:10
  • \$\begingroup\$ Time.deltaTime retrieves seconds since last update. That means when deltaTime is not less than one, it took more than a second to process the last frame. Wouldn't that suggest problems, itself? \$\endgroup\$
    – Gnemlock
    Commented Aug 25, 2016 at 16:12
  • \$\begingroup\$ The original code does something a bit different, since it's not adding deltaTime to score, but adding total time. That means score goes up non-linearly, increasing faster and faster the longer the level runs. If that was deliberate, then we'd probably want to accumulate a levelTime value, and then compute score as a nonlinear function of levelTime, rather than try to accumulate score directly. \$\endgroup\$
    – DMGregory
    Commented Aug 25, 2016 at 16:14
  • 1
    \$\begingroup\$ I must admit I didn't know that was how it worked. But it wasn't my desired behavior. I prefer the script as is. Thanks for the explanation, I learned a lot about Time.deltatime. \$\endgroup\$ Commented Aug 26, 2016 at 7:45

You must log in to answer this question.

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