Advertisement

I need help with an error in my Unity 2D Game

Started by November 09, 2022 11:34 AM
2 comments, last by Aybe One 1 year, 11 months ago

Hello everyone! I've recently started making a 2D RPG Top Down game, a sort of Dungeon Crawler, following this YouTube guide: https://www.youtube.com/watch?v=b8YUfee_pzc&list=WL&index=5&ab_channel=Epitome

I'm currently at the Floating Text section (2:43:00) onwards, but I get this error everytime I collide with a chest. The sprite changes to the empty chest, but the floating text that should say “+5 Gold!” doesn't appear. I'll attach my scripts. From what I understood, I think that the FloatingText variable doesn't get created properly in the GetFloatingText function, which eturns a null value, and this leads to the NullReferenceException error when trying to assign values like “msg” to it. I want to clarify that I attached everything in the right GameObject slots in the Inspector. The error should be around GameManager.cs or FloatingTextManager.cs, the other scripts work fine in other scenarios.

NullReferenceException: Object reference not set to an instance of an object

FloatingTextManager.Show (System.String msg, System.Int32 fontSize, UnityEngine.Color color, UnityEngine.Vector3 position, UnityEngine.Vector3 motion, System.Single duration) (at Assets/Scripts/FloatingTextManager.cs:23)

GameManager.ShowText (System.String msg, System.Int32 fontSize, UnityEngine.Color color, UnityEngine.Vector3 position, UnityEngine.Vector3 motion, System.Single duration) (at Assets/Scripts/GameManager.cs:39)

Chest.OnCollect () (at Assets/Scripts/Chest.cs:16)

Collectable.OnCollide (UnityEngine.Collider2D coll) (at Assets/Scripts/Collectable.cs:12)

Collidable.Update () (at Assets/Scripts/Collidable.cs:25)

EDIT: I solved the problem by changing the FloatingText prefab to a Legacy Text instead of the default TextMeshPro.

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

public class Collidable : MonoBehaviour
{

    public ContactFilter2D filter;
    private BoxCollider2D boxCollider;
    private Collider2D[] hits = new Collider2D[10];

    protected virtual void Start()
    {
        boxCollider = GetComponent<BoxCollider2D>();
    }

    protected virtual void Update()
    {
        boxCollider.OverlapCollider(filter, hits);
        for (int i = 0; i < hits.Length; i++)
        {
            if (hits[i] == null)
                continue;

            OnCollide(hits[i]);

            hits[i] = null;
        }
    }

    protected virtual void OnCollide(Collider2D coll)
    {
        Debug.Log(coll.name);
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Collectable : Collidable
{
    protected bool collected;

    protected override void OnCollide(Collider2D coll)
    {
        if (coll.name == "Player")
            OnCollect();
    }

    protected virtual void OnCollect()
    {
        collected = true;
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Chest : Collectable
{
    public Sprite emptyChest;
    public int goldAmount = 5;

    protected override void OnCollect()
    {
        if (!collected)
        {
            collected = true;
            GetComponent<SpriteRenderer>().sprite = emptyChest;
            GameManager.instance.ShowText("+" + goldAmount + " Gold!", 16, Color.yellow, transform.position, Vector3.up * 50, 1.5f);
        }
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class GameManager : MonoBehaviour
{
    public static GameManager instance;

    private void Awake()
    {
        if (GameManager.instance != null)
        {
            Destroy(gameObject);
            return;
        }

        instance = this;
        SceneManager.sceneLoaded += LoadState;
        DontDestroyOnLoad(gameObject);
    }

    // Resources
    public List<Sprite> playerSprites;
    public List<Sprite> weaponSprites;
    public List<int> weaponPrices;
    public List<int> xpTable;

    // References
    public Player player;
    // public Weapon weapon; ...
    public FloatingTextManager floatingTextManager;

    public int gold;
    public int experience;

    public void ShowText(string msg, int fontSize, Color color, Vector3 position, Vector3 motion, float duration)
    {
        floatingTextManager.Show(msg, fontSize, color, position, motion, duration);
    }

    public void SaveState()
    {

        string s = "";

        s += "0" + "|";
        s += gold.ToString() + "|";
        s += experience.ToString() + "|";
        s += "0";

        PlayerPrefs.SetString("SaveState", s);
    }

    public void LoadState(Scene s, LoadSceneMode mode)
    {

        if (!PlayerPrefs.HasKey("SaveState"))
            return;

        string[] data = PlayerPrefs.GetString("SaveState").Split('|');

        // Change player skin
        gold = int.Parse(data[1]);
        experience = int.Parse(data[2]);
        // Change weapon level

    }

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

public class FloatingTextManager : MonoBehaviour
{
    public GameObject textContainer;
    public GameObject textPrefab;

    private List<FloatingText> floatingTexts = new List<FloatingText>();
    
    private void Update()
    {
        foreach (FloatingText txt in floatingTexts)
            txt.UpdateFloatingText();
    }

    public void Show(string msg, int fontSize, Color color, Vector3 position, Vector3 motion, float duration)
    {
        FloatingText floatingText = GetFloatingText();
        
        floatingText.txt.text = msg;
        floatingText.txt.fontSize = fontSize;
        floatingText.txt.color = color;
        floatingText.go.transform.position = Camera.main.WorldToScreenPoint(position);
        floatingText.motion = motion;
        floatingText.duration = duration;
        
        floatingText.Show();
    }

    private FloatingText GetFloatingText()
    {
        FloatingText txt = floatingTexts.Find(t => !t.active);

        if (txt == null)
        {
            txt = new FloatingText();
            txt.go = Instantiate(textPrefab);
            txt.go.transform.SetParent(textContainer.transform);
            txt.txt = txt.go.GetComponent<Text>();

            floatingTexts.Add(txt);
        }

        return txt;
    }
}
Advertisement

It's a bit late for an answer but anyway…

FloatingText.txt property is supposed to have a value of a component Text but it doesn't.
It could be a prefab that got broke during an upgrade because of Unity internal crap, heh.
There are ways to fix the broken prefabs in the Inspector.

A good way to debug these kind of errors is to use one of the overloads of Debug.Log that accepts an object for the context and log a message at that position in the code.
Providing that the context object is not null, you simply click that log message in the console, Unity will reveal the object in Hierarchy and thus, you would instantly see in the Inspector that, either:

  • there is no Text component → code supposed to add it, didn't, lookout for the code block responsible for that or maybe simply adding one might be sufficient
  • there is a Text component but it's grayed out, original value from prefab has been overridden/whatever → you can use the context menu to reset it to prefab value

This topic is closed to new replies.

Advertisement