Tracking Score / Sorting Score

Hi,

I’m currently doing this course since it’s updated and I wanna go a bit beyond. My idea is that I want to be able to have 4 different players play the game and then they get a score. (So not % instead it will be points.)

In the end scene I wanna do the placements.

I use Playerprefs to store the score so that isn’t a problem but could someone please just point me in the direction of how to populate a list with two or more columns.

Example:

Points : Name
8 Martin
6 Joel
5 Johanna
4 Marika

When the list is populated I want to sort it by 1 column (Points) but I want the other column to still stick to it (In other words 8 points should still be connected to Martin.)

I get that I took this a bit too far and that it’s almost off topic but I don’t need a full answer but could someone just point me in a direction of:

  1. How to populate list with 2 columns
  2. How to sort that list (by one column)

Ps. Doesnt have to be a list if you have a better way.

Any help truly is appreciated I’m currently in a weird youtube/stackoverflow/unity forums loop that gives me small answers into specifics which I can’t really piece together.

All the best

//Martin

Hi Murten,

Welcome back! :slight_smile:

Using the PlayerPrefs to store the score is a good idea.

Regarding the sorting, have you already seen the following?
https://zetcode.com/csharp/sortlist/

The examples show the same what you want to do. The integers represent the “salary” instead of the “score” but that does not matter.

Did this help?


See also:

Hi Nina,

Thank you so much for the answer, sometimes it’s hard to grasp the actual problem when you get thrown in from the side and the site you pasted instead managed to explain from the start so now it works.

I do however have two questions but one is really small so hopefully that will help. I managed to go with a lambda expression.

Small question:

When I print the List it only prints two lines with the Debug Log, but when I click on the line in the “Debug Log” then it shows in the bottom how there actually is 3 lines. I tried to uncollapse/click around. Any idea what the heck I managed to do?

Other question:

Since it works now and Im extactic I want to be able to bring out the values from the List and just placed them in the Text Fields on the scene. Do you have any source on how to just pull the values out of a list?

Example would be String WinnerName = 1 row, first column of list.
Int WinnerScore = 1 Row, Second Column of list.

Please do say if it’s told in the page you sent me, I might have missed it but am pretty sure I didn’t.

Once again, Thanks!

According to the manual, the console is able to display up to 10 lines. If you need to debug more than a few values, learn how to check the value of variables in your script editor. Debug.Log is fine for a bunch of values but exhausting if you do a lot with data.

You could simply iterate over the list. See here. If you need to access a specific element at a specific index, you do this: myList[1]; (if you want to access the second element in the List object).

How are you getting on with this, @Murten?

Hey Nina,

Sorry for not answering earlier, rude of me. I just kept digging. I can not even tell you how off-track front he course I got in order to find the answer to the question.

My goal was to:

  1. Simply save score in PlayerPrefs for different players
  2. in the end of some minigames sort the scores (With the score sticking to the names.)
  3. From the sorting pull out the “Winner Name” and “Winner Score” and place them in two different textboxes.

Now I might have gone off the rails with this but for me it seemed to be absolutely impossible to do. My solution in the end, after learning alot but screaming even more, was to create a SaveLoadSystem.

I don’t know if your interested but I will paste the code. Through my system some extra strengths gets added like the fact that I can store by ID so I can store information per gameID. If I default the GameID at Save to 0 then I store a players score together. There is some bloated code that I still don’t get to work like

public static void SavePerson(String personName, int score, int gameId = 0, bool useAdditiveScoring = false)

The additiveScoring really isn’t needed there if the game isn’t of id 0, atleast not for my game.

Anyhow below is the SaveLoadSystem:

public static class SaveLoadSystem
{

    public static void SavePerson(String personName, int score, int gameId = 0, bool useAdditiveScoring = false)
    {
        Dictionary<string, int> scorelist = LoadData(gameId); 

        if (scorelist.ContainsKey(personName))
        {
            if (useAdditiveScoring)
            {
                int oldScore = scorelist[personName];
                score += oldScore;
            }
            scorelist[personName] = score;

        }
        else
        {
            scorelist.Add(personName, score);
        }

        SaveData(scorelist, gameId);
        Debug.Log($"Saved person {personName} with a score of {score}.");

    }



    public static int GetPlayerScore(string playerName, int gameId = 0) 
    {
        Dictionary<string, int> scorelist = LoadData(gameId);
        if (scorelist.ContainsKey(playerName))
        {
            return scorelist[playerName];
        }
        return -1;

    }



    public static void RemovePlayer(string playerName, int gameId = 0)
    {
        Dictionary<string, int> scorelist = LoadData(gameId); 
        if (scorelist.ContainsKey(playerName))
        {
            scorelist.Remove(playerName);
            SaveData(scorelist, gameId);
        }
        else
        {
            Debug.Log("Player " + playerName + " does not exist for this game!");
        }
    }


    public static void RemoveAllData(int gameId = 0)
    {
        PlayerPrefs.DeleteKey("ScoreListData" + gameId);
    }


    public static Dictionary<string, int> LoadData(int gameId = 0, bool sorted = true)
    {
        Dictionary<string, int> scorelist = new Dictionary<string, int>(); 

        if (PlayerPrefs.HasKey("ScoreListData" + gameId))
        {

            string scoreListData = PlayerPrefs.GetString("ScoreListData" + gameId); 

            string[] dataPairs = scoreListData.Split('|');


            foreach (string dataPair in dataPairs)
            {

                string[] data = dataPair.Split(';');


                if (data.Length != 2)
                {
                    break;
                }


                int score;
                if (int.TryParse(data[1], out score))
                {

                    scorelist.Add(data[0], score);

                }
                else
                {
                    Debug.LogError("Save Load System: An error has occurred loading the save data. Integer could not be parsed correctly");
                }
            }


        }
        else
        {
            Debug.LogWarning("Save Load System: Data was loaded but there was no data found. Something is wrong if you see this message more than once.");
        }


        if (sorted)
        {

            Dictionary<string, int> sortedScoreList = new Dictionary<string, int>();


            var sortedDict = from entry in scorelist orderby entry.Value descending select entry;


            foreach (KeyValuePair<string, int> entry in sortedDict)
            {
                sortedScoreList.Add(entry.Key, entry.Value);
            }


            return sortedScoreList;
        }
        return scorelist;

    }


    private static void SaveData(Dictionary<string, int> scoreList, int gameId)
    {
        string savedString = "";
        foreach (KeyValuePair<string, int> entry in scoreList)
        {
            savedString += entry.Key + ";" + entry.Value + "|";
        }

        PlayerPrefs.SetString("ScoreListData" + gameId, savedString);
    }




}

Below is an example of how to use it.

public class SaveLoadTest : MonoBehaviour
{

    Dictionary<string, int> scoreList = new Dictionary<string, int>();
    Dictionary<string, int> scoreList2 = new Dictionary<string, int>();
    List<Text> nameTextList = new List<Text>();
    List<Text> scoreTextList = new List<Text>(); 

    void Start()
    {

        SaveLoadSystem.RemoveAllData();
        SaveLoadSystem.SavePerson("Jack", 12);
        SaveLoadSystem.SavePerson("TestPerson", 4);
        SaveLoadSystem.SavePerson("Emily", 10);
        SaveLoadSystem.SavePerson("Emily", 15, 2);



        scoreList = SaveLoadSystem.LoadData(0, false);
        scoreList2 = SaveLoadSystem.LoadData(2);

        foreach (KeyValuePair<string, int> entry in scoreList)
        {
            Debug.Log(entry.Key + " has a score of " + entry.Value);
        }

        Debug.Log("-------");


        scoreList = SaveLoadSystem.LoadData(0, true);


        foreach (KeyValuePair<string, int> entry in scoreList)
        {
            Debug.Log(entry.Key + " has a score of " + entry.Value);
        }



        for (int i = 0; i < nameTextList.Count; i++)
        {
            nameTextList[i].text = scoreList.ElementAt(i).Key;
            scoreTextList[i].text = scoreList.ElementAt(i).Value.ToString();
        }
    }
}

It still lacks some and there is code that I could make a lot better but this is just the result of 1 week of sadness, confusion, full blown crying and adding more to some code that I thought would be simple.

Hope it makes any sense:)

I will now like Hans and Grettel try to find my way back to the course

1 Like

Good job so far! I skimmed your code, and it looks fine to me. It is readable and makes sense. :slight_smile:

Don’t worry too much if you haven’t been able to implement all ideas (yet). You have a solution now, and maybe you want to enhance it in the future, in this project or in future projects where you want to reuse your save and load system.

Keep it up!

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms