1

Solved: It looks like it can't find the current player. When commenting out the code below(line 74), it works. Anyway, thanks for the help!

    if (!scores.Contains (player)) 
    {
        scores.Add (player);
    }

So i followed this guide https://marcelofs.com/blog/how-to-create-a-quick-top10-for-your-unity-game-with-firebase/

It was very simple and easy to understand and i can confirm that uploading and downloading to the database works. The problem is when i try to access the data that is downloaded from Firebase and saved in a C# list. I am not an expert in C#, but i try to learn by making games. And i usually find a solution, but this one is tricky.

So what i understand from this code is that it downloads all the scores and uses a foreach loop to save the data in the list "scores". When that is done, it goes to AddScores() and start to sort the list. And here is the problem, Unity says "Object reference not set to an instance of an object". I tried to do everything without sorting, and the same error comes at the foreach loop when getting the data from the list. And it is here i understand that they cant get any data from the scores list. And i am really stuck.

Here is the code(i know that the firebase url is wrong):

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

public class TopScores : MonoBehaviour {

//this is set by UploadPlayerScore and used to compare if the player is in the Top10 returned by the server, or otherwise add it as the 11th result
public static Score player;

public static void SetPlayer(string id, string name, int score, string category)
{
    player = new Score();
    player.id = id;
    player.name = name;
    player.score = score;
    player.category = category;
    player.time = new DateTime();
}

//Have a button point to this to exit
public void Quit()
{
    Application.Quit();
}

//you'll need to set this in unity as the parent 'Scores' object shown above
public GameObject scorePanel;
protected List<Score> scores = new List<Score>();
protected void Start()
{
    DownloadScores();
}

protected void DownloadScores()
{

    UnityHTTP.Request someRequest = new UnityHTTP.Request("get", "https://myfirebase.firebaseio.com/scores.json"/*?orderBy=\"score\"&limitToLast=10"*/);
    someRequest.Send((request) => {
        Hashtable decoded = (Hashtable)JSON.JsonDecode(request.response.Text);
        if (decoded == null)
        {
            Debug.LogError("server returned null or     malformed response ):");
            return;
        }

        foreach (DictionaryEntry json in decoded)
        {
            Hashtable jsonObj = (Hashtable)json.Value;
            Score s = new Score();
            s.id = (string)json.Key;
            s.name = (string)jsonObj["name"];
            s.score = (int)jsonObj["score"];
            Debug.Log("Score " + s.score);
            s.category = (string)jsonObj["cat"];

            //gotta convert it!
            DateTime dtDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, System.DateTimeKind.Utc);
            s.time = dtDateTime.AddMilliseconds((long)jsonObj["time"]).ToLocalTime();

            scores.Add(s);
        }
        AddScores();
    });
}

protected void AddScores()
{
    //no dupes
    if (!scores.Contains(player))
    {
        scores.Add(player);
    }

    //firebase usually returns sorted content, but that's not guaranteed by the JSON format
    scores.Sort((Score x, Score y) => { return x.score.CompareTo(y.score); });

    //we'll be filling top to bottom
    scores.Reverse();

    int i = 0;
    foreach (Score s in scores)
    {
        if (i > 10)
        {
            break;
        }
        Transform panel = scorePanel.transform.Find("Panel " + i);
        Debug.Log(panel);
        Transform score = panel.Find("score");
        Debug.Log(s.score);
        score.GetComponentInChildren<Text>().text = s.score + "";
        //panel.Find(s.category).gameObject.SetActive(true);
        panel.Find("name").GetComponent<Text>().text = s.name;
        if (!s.Equals(player))
        {
            //the player might not come from the server, so 'time' will be null
            panel.FindChild("time").GetComponent<Text>().text = s.time.ToString("yyyy-MM-dd");
        }
        i++;
    }
}

public class Score
{
    public string id;
    public string name;
    public int score;
    public string category;
    public DateTime time;

    public override bool Equals(System.Object obj)
    {
        if (obj == null)
        {
            return false;
        }
        Score s = obj as Score;
        if ((System.Object)s == null)
        {
            return false;
        }
        return id == s.id;
    }
}
}
Thomaslian
  • 11
  • 4
  • Do you know which line it's throwing that exception at? Do any of the `score` or `panel` children have a Text component? The error suggests that there is an object that is null somewhere in your code, so something isn't being initialized. In this code scorePanel is never initialized, double check that it is set from the editor when this code is run. – Kolichikov Aug 25 '16 at 18:37
  • The scorepanel is initialized in unity, and if i set an number instead of the s.score, it will work. Example "score.GetComponentInChildren().text = 3;" it will update the first row with score 3 on my top 10 panel instead of "score.GetComponentInChildren().text = s.score + "";" It is at line 79, when it starts to sort. And the score variable does have a text component, the panel is a row that has the score gameobject as a children – Thomaslian Aug 25 '16 at 18:49
  • Sorry, I meant where does it break when you remove sorting (you mentioned it still fails when you try to do it without sortying). Also, as a rule of thumb, it's good practice to override GetHashCode if you are overriding Equals (see [here](http://stackoverflow.com/questions/371328/why-is-it-important-to-override-gethashcode-when-equals-method-is-overridden) for a good explanation). Maybe not important here though. – Kolichikov Aug 25 '16 at 18:57
  • If i comment out line 79 (sorting) and line 82 (`scores.Reverse()`) the next stop will be at line 94 `Debug.Log(s.score);` same error. I will take a look on the GetHashCode when i finish this error, thanks for the tip – Thomaslian Aug 26 '16 at 11:15
  • An update on commenting out the sorting and scores.Reverse (Line 79 to 78). It does now work, i don't know what happend. I do not get any error on `Debug.Log(s.score);` anymore. I will take a closer look on sorting the list – Thomaslian Aug 26 '16 at 11:51

2 Answers2

0

Pay attention to the tutorial you are following.

You had

score.GetComponentInChildren<Text>().text = s.score + "";

Meanwhile, in the tutorial, it says

score.GetComponent<Text>().text = s.score + "";

The score GameObject should have the Text attached to it.

Programmer
  • 121,791
  • 22
  • 236
  • 328
  • Yes i know, i though it did not find the gameobject at first, so i tried to make a child text gameobject of the score gameobject. This was before i realized it was the s.score that is not initialized. This has nothing to do with the error tho. – Thomaslian Aug 26 '16 at 11:09
  • If `GetComponentInChildren()` returns null and you try to use it, you will get an exception. Since that's not the problem, is this problem now fixed? – Programmer Aug 26 '16 at 11:12
  • No, i still can't get pass the scores.Sort at line 79. Still gives me that error – Thomaslian Aug 26 '16 at 11:48
0

It looks like it can't find the current player. When commenting out the code below(line 74), it works. Anyway, thanks for the help!

if (!scores.Contains (player)) 
{
    scores.Add (player);
}
Thomaslian
  • 11
  • 4