Home > Back-end >  Trying to record level time data and print to screen at the end Unity 2D
Trying to record level time data and print to screen at the end Unity 2D

Time:01-01

So I have a 2D platformer parkour game which holds a timer when player starts level. I have 5 levels and at the end of each level, I want to keep the last time value and display them at the end of the game.

So far, I tried to hold the last time value when player triggers the End portal and store them in an array in the code below. Here are the scripts:

Time Data Manager Script:

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

public class timeDataManager : MonoBehaviour
{
    public string[] timeDataArr;
    void Start(){
    }
    void Update(){
        Debug.Log(timeDataArr[SceneManager.GetActiveScene().buildIndex-1]);
    }

    public void AddTimeData(string timeData, int levelBuildIndex){
        timeDataArr[levelBuildIndex-1] = timeData.ToString();
    }
}

End Portal Script:

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

public class EndPortal : MonoBehaviour
{
    public AudioSource aSrc;
    private int sceneNumber;
    public GameObject bgAudio;
    public Text scoreText;
    string textData;
    public timeDataManager tDManager;
    void Start(){
        sceneNumber = SceneManager.GetActiveScene().buildIndex;
        tDManager = GameObject.FindGameObjectWithTag("TimeDataManager").GetComponent<timeDataManager>();
    }
    
    void OnTriggerEnter2D(Collider2D col){
        if (col.gameObject.tag == "Player"){
            aSrc.Play();
            Destroy(bgAudio);
            textData = scoreText.text;
            Debug.Log(textData);
            Debug.Log(sceneNumber);
            tDManager.AddTimeData(textData,sceneNumber);
            SceneManager.LoadScene(sceneBuildIndex:sceneNumber 1);
        }
    }
}

As I said before, I tried to keep all timer values at the end of each level and store them in an array in my timeDataManager script. But it's not working.

Any ideas on how to fix? Or do you have any other ideas? Thanks a lot for your time.

CodePudding user response:

Issylin's answer is a better solution for your needs but i want to mention couple of things about your code.

One thing about your timeDataArr. If you don't touch it in inspector, you need to initialize it first. So let's say, if you want to hold 5 levels of time data, you need to do something like;

public string[] timeDataArr = new string[5];

or

public class timeDataManager : MonoBehaviour
{
    public string[] timeDataArr;
    public int sceneAmount_TO_HoldTimeData = 5;
    
  void Start()
  {
     timeDataArr = new string[sceneAmount_TO_HoldTimeData];
  }
}

or

public class timeDataManager : MonoBehaviour
{
    public string[] timeDataArr;
    public int sceneAmount_NOT_ToHoldTimeData = 1;
    
  void Start()
  {
     timeDataArr = new string[SceneManager.sceneCountInBuildSettings - sceneAmount_NOT_ToHoldTimeData];
  }
}

Another thing is you need to be careful about levelBuildIndex-1. If you call that in first scene,

SceneManager.GetActiveScene().buildIndex

will be 0 and levelBuildIndex-1 will be -1 or in Debug part it will be timeDataArr[-1] but array indexes must start with 0. So it will throw an error.

One more thing, this is not an error or problem. Instead of this part

tDManager = GameObject.FindGameObjectWithTag("TimeDataManager").GetComponent<timeDataManager>();

you can do

tDManager = FindObjectOfType<timeDataManager>();

CodePudding user response:

There are several way to achieve what you're trying to do.

The easier would be to use a static class for such a simple data like the one you're carrying through your game.

using System.Collections.Generic;

public class Time_Data
{
    /// TODO
    /// Add the members
    /// e.g. your time format as string or whatever,
    /// the scene index, etc
}

public static class Time_Manager
{
    private static List<Time_Data> _times;

    public static void Add_Time(in Time_Data new_time)
    {
        _times.Add(new_time);
    }

    public static List<Time_Data> Get_Times()
    {
        return _times;
    }

    public static void Clear_Data()
    {
        _times.Clear();
    }
}

Use it like any other static methods within your OnTriggerEnter2D call.

Time_Manager.Add( /* your new data here */ );

The other way, if you intend to stay with a game object within your scenes, would be to use the DontDestroyOnLoad method from Unity so your game object which has your script timeDataManager would remain.

Note that in your code, using string[] might be unsafe. For your use of it, consider using a List<string>.

  • Related