**SOLVED** Still cant get best time working

So i really am stumped… With the code below the score shows the time that the timer is stopped… I.e. the end of the level… So if the level takes 1 min and 20 seconds to complete than the Time finished shows 1 min 20 secs…
Then for some reason the Best time also shows this same score… Then when i replay the level the time completed goes back to 0 as intended, but so does the best score… I need the best score to stay at the the previous time completed and only change if the new time is less that the previous time… I suck royaly at math so maybe my calculations are all jagged up… Maybe its my data save thats also wrong i dunno… I completely started over and made a simple scene with two buttons, start timer and stop. and made two number fields that display score and best score… and the timer text…

TimerScore Script.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class TimerScore : MonoBehaviour {

    public Text timerText;
    public Text score;
    public Text best;



  

    public float startTime;
    public float stopTime;

    public bool isStarted;

    // Use this for initialization
    void Start ()
    {

        //Game.current._highScore = 999;
        best.text = "" + Mathf.Round(Game.current._highScore);
        SaveLoad.LoadGame();


    }

    public void StartThis()
    {
        startTime = 0;
        isStarted = true;

      
    }

    public void StopThis()
    {
        isStarted = false;
        stopTime = Time.deltaTime - startTime;
        startTime += Time.deltaTime;

        if(startTime > stopTime)
        {
           
            Debug.Log("Setting best to starttime");
            Game.current._highScore = startTime;
            best.text = "" + Mathf.Round(Game.current._highScore);
            Game.current.newTime = true;
            SaveLoad.SaveGame();
        }
        else if (startTime < stopTime)
        {
            Debug.Log("Setting best to stoptime");
            Game.current._highScore = stopTime;
            best.text = "" + Mathf.Round(Game.current._highScore);
            Game.current.newTime = false;
            SaveLoad.SaveGame();
        }
       

     

     }


   
    // Update is called once per frame
    void Update () {

        if (isStarted)
        {
          
            startTime += Time.deltaTime;
            float minutes = startTime / 60;
            float seconds = startTime % 60;

            timerText.text = string.Format("{0:00} : {1:00}", minutes, seconds);
            score.text = "" + Mathf.Round(startTime);



        }
    }

  
}

My Two Scripts for saving data…

Game Script…

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[System.Serializable]




public class Game
{

    public static Game current = new Game();
    public float _highScore;
    public float highScore;
    public bool newTime;




}

And my SaveLoad Script…

using UnityEngine;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;

public static class SaveLoad
{

    public static void SaveGame()
    {
        BinaryFormatter bf = new BinaryFormatter();
        if (File.Exists(Application.persistentDataPath + "/SavedGame.dat"))
        {

            FileStream file = File.Open(Application.persistentDataPath + "/SavedGame.dat", FileMode.Open);
            Game game = new Game();
            game.highScore = Game.current.highScore;
            game._highScore = Game.current._highScore;
            game.newTime = Game.current.newTime;
            bf.Serialize(file, Game.current);
            file.Close();
        }
        else
        {

            FileStream file = File.Create(Application.persistentDataPath + "/SavedGame.dat");
            Game game = new Game();
            game.highScore = Game.current.highScore;
            game._highScore = Game.current._highScore;
            game.newTime = Game.current.newTime;
            bf.Serialize(file, Game.current);
        }


    }

    public static void LoadGame()
    {
        if (File.Exists(Application.persistentDataPath + "/SavedGame.dat"))
        {
            BinaryFormatter bf = new BinaryFormatter();
            FileStream file = File.Open(Application.persistentDataPath + "/SavedGame.dat", FileMode.Open);
            Game game = (Game)bf.Deserialize(file);
            file.Close();

            Game.current.highScore = game.highScore;
            Game.current.highScore = game._highScore;
            Game.current.newTime = game.newTime;
           
            Debug.Log("Loaded The File");
        }
        else
        {
            Debug.Log("File Does Not Exist");
        }
    }
}

I have even tried this way…

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class TimerScore : MonoBehaviour {

    public Text timerText;
    public Text score;
    public Text best;



  

    public float startTime;
    public float stopTime;

    public bool isStarted;

    // Use this for initialization
    void Start ()
    {

        //Game.current._highScore = 999;

        SaveLoad.LoadGame();
        if(Game.current.newTime)
        {
            Debug.Log("start best is starttime");
            Game.current._highScore = stopTime;
            best.text = "" + Mathf.Round(-Game.current._highScore);

           
        }
        else if (!Game.current.newTime)
        {
            Debug.Log("start best is stoptime");
            Game.current._highScore = stopTime;
            best.text = "" + Mathf.Round(-Game.current._highScore);


        }
        SaveLoad.LoadGame();
    }

    public void StartThis()
    {
        startTime = 0;
        isStarted = true;

      
    }

    public void StopThis()
    {
        isStarted = false;
        stopTime = Time.deltaTime - startTime;
        startTime += Time.deltaTime;

        if(startTime > stopTime)
        {
           
            Debug.Log("Setting best to starttime");
            Game.current._highScore = startTime;
            best.text = "" + Mathf.Round(Game.current._highScore);
            Game.current.newTime = true;
            SaveLoad.SaveGame();
        }
        else if (startTime < stopTime)
        {
            Debug.Log("Setting best to stoptime");
            Game.current._highScore = stopTime;
            best.text = "" + Mathf.Round(Game.current._highScore);
            Game.current.newTime = false;
            SaveLoad.SaveGame();
        }
       

     

     }


   
    // Update is called once per frame
    void Update () {

        if (isStarted)
        {
          
            startTime += Time.deltaTime;
            float minutes = startTime / 60;
            float seconds = startTime % 60;

            timerText.text = string.Format("{0:00} : {1:00}", minutes, seconds);
            score.text = "" + Mathf.Round(startTime);



        }
    }

  
}

Correction start is this in above script…

void Start ()
    {

        //Game.current._highScore = 999;

        SaveLoad.LoadGame();
        if(Game.current.newTime)
        {
            Debug.Log("start best is starttime");
            Game.current._highScore =startTime;
            best.text = "" + Mathf.Round(Game.current._highScore);

           
        }
        else if (!Game.current.newTime)
        {
            Debug.Log("start best is stoptime");
            //Game.current._highScore = stopTime;
            best.text = "" + Mathf.Round(Game.current._highScore);


        }
        SaveLoad.LoadGame();
    }

Not sure why you have Time.deltaTime - startTime.

In any event, rather than look over all of that…

It should be as simple as :

float startTime = Time.time;
// later on, when finishing that round..
float duration = Time.time - startTime;
if(duration < bestTime) {
   // adjust best time + text field, etc..
  }

Got It working with your help buddy thanks… Changed some stuff but heres the code for anyone else…

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class TimerScore : MonoBehaviour {

    public Text timerText;
    public Text score;
    public Text best;



  

    public float startTime;
    public float _startTime;
    public float stopTime;
    public float previousTime;
    public float bestTime;
    public bool isStarted;
  
    // Use this for initialization
    void Start ()
    {

        Game.current._newTime = -10;
       // SaveLoad.LoadGame();
      
        best.text = "" + Mathf.Round(-Game.current._newTime);
    }

    public void StartThis()
    {
       
        isStarted = true;

        startTime = 0;
    }

    public void StopThis()
    {
        isStarted = false;




        bestTime = -Game.current._newTime;
        stopTime = startTime;

        if(stopTime < bestTime)
        {
            Game.current._newTime = -stopTime;

            best.text = "" + Mathf.Round(stopTime);


           SaveLoad.SaveGame();

        }

     }


   
    // Update is called once per frame
    void Update () {

        if (isStarted)
        {
            _startTime = Time.deltaTime;
            startTime += Time.deltaTime;
            float minutes = startTime / 60;
            float seconds = startTime % 60;

            timerText.text = string.Format("{0:00} : {1:00}", minutes, seconds);
            score.text = "" + Mathf.Round(startTime);



        }
    }

  
}

Well, I’m glad you got it working.

The only thin is now, it still doesnt save the high score on restart

Well, if you’re restarting in the same scene, just make sure you leave the best score text unchanged.
if you’re doing it from a scene change, then you’d have to carry the variable over , with:

  • dontdestroyonload
  • playerprefs
  • static variable
    or something else that keeps the value around :wink:

Im using serialized data. I save the float of the bets time. I also tried saving the best time as an int and just add the best time to it if its less than the previous.

Okay, so your data is not saving or being retrieved properly?

btw, it looks like you’re missing a file.Close() in one of your methods.

i added it, still no change…

Well, I did not think that was the cause, actually. Just thought I’d mention it when I noticed.

Not sure what to tell you. Why not just try a simple save + load & retrieve the values… see if it’s working?
Sounds simplest to me.

Yeah i can do a simple player pref but we both know thats crude. Plus people tend to hack a game any chance they can. Thats why i wanted to use serialization. I used it before for gold amounts but not for keeping a time based score.

Ya, but all i was saying was just do a simple test. Make sure that’s not the issue. Then check the next thing (maybe what you assign to the text object)… step by step and track down the bug. :slight_smile:

I wasn’t suggesting you move to player prefs. I figured you had your reasons for the way you were doing it.

Ive been looking. And to be honest i am stuck. I dont think ive spent so much time on a script as i have on this. It seems so simple yet i’m puzzled. I’ve used Logs where needed. Ive tracked that the values are being updates, ive tracked that the data is indeed being saved and loaded. Thanks for the help though buddy.

Sure, well if you already did all that, then the problem must be with setting the Text object… that’s the only guess I’d have to check next :slight_smile:

The text is updating fine. I can get the score and best score now. I** The problem is saving the value of the best score versus the current score and then saving it to the serialization data… Then having that high score to show on restart.

I think my problem is that im trying to save a time instead of a number. Like its different if im saving 10 but im saving minutes and seconds…

It may be sloppy but i finally got it!!! Here is the final scripts if anyone wants them. Enjoy!

TimerScore Script in an empty gameobject

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class TimerScore : MonoBehaviour
{
    public static TimerScore TC;
    public Text timerText;
    public Text score;
    public Text best;

    public bool isStarted;

    public float _startTime;
    int testNum;



    public void Awake()
    {
        SaveLoad.LoadGame();
    }

    void Start()
    {

        best.text = "" + Game.current._highscore;

        TC = this;

    }

  
    void Update()
    {


        if (isStarted)
        {

            _startTime += Time.deltaTime;

            timerText.text = "" + Mathf.Round(_startTime);

        }
    }


    public void StartThis()
    {
     
        isStarted = true;
     
        _startTime = 0;
        score.text = "" + 0;
        Game.current.firstTime = false;

        best.text = "" + Game.current._highscore;
      
    }


    public void StopThis()
    {
     
        isStarted = false;

        score.text = "" + Mathf.Round(_startTime);
        Game.current.score = (int)Mathf.Round(TC.GetComponent<TimerScore>()._startTime);

        Game.current.firstTime = false;
        SaveLoad.SaveGame();

        if(Game.current.score < Game.current._highscore)
        {
            Debug.Log("Updating Score to _starttime");
            best.text = "" + Mathf.Round(_startTime);
            Game.current._highscore = (int)Mathf.Round(TC.GetComponent<TimerScore>()._startTime);
            SaveLoad.SaveGame();
        }
        else {
            Debug.Log("Leaveing text to be _highscore");
            best.text = "" + Mathf.Round(Game.current._highscore);
            SaveLoad.SaveGame();
        }
    }
}

Game Script for binary format…

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[System.Serializable]




public class Game
{

    public static Game current = new Game();
   
    public float score;
    public int _highscore;
    public bool firstTime;





}

And the SaveLoad Script for saving and loading items in Game script…

using UnityEngine;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;

public static class SaveLoad
{

    public static void SaveGame()
    {
      
      
            BinaryFormatter bf = new BinaryFormatter();

            FileStream file = File.Create(Application.persistentDataPath + "/SaveGame.dat");
            Game game = new Game();



           
            game.score = Game.current.score;
            game._highscore = Game.current._highscore;
        game.firstTime = Game.current.firstTime;





            bf.Serialize(file, Game.current);
            file.Close();
            Debug.Log("Saved The File");
      


    }

    public static void LoadGame()
    {
        if (File.Exists(Application.persistentDataPath + "/SaveGame.dat"))
        {
            BinaryFormatter bf = new BinaryFormatter();
            FileStream file = File.Open(Application.persistentDataPath + "/SaveGame.dat", FileMode.Open);
            Game game = (Game)bf.Deserialize(file);
            file.Close();

            
            Game.current.score = game.score;
            Game.current._highscore = game._highscore;
            Game.current.firstTime = game.firstTime;
          
            Debug.Log("Loaded The File");
        }
        else
        {
            Debug.Log("File Does Not Exist");
        }
    }
}

Hey, cool, glad you got it working :slight_smile: