[Tilevania] Question on tutorial 145

Hi Nina,

(This was posted in Udemy but no reply.)

I cannot understand why I get this error. Can you check the entire file for me?

NullReferenceException: Object reference not set to an instance of an object StarDisplay.UpdateDisplay () (at Assets/Scripts/StarDisplay.cs:19)

StarDisplay.Start () (at Assets/Scripts/StarDisplay.cs:14)

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

public class StarDisplay : MonoBehaviour
{
[SerializeField] int stars = 100;
Text starText;

void Start()
{
    starText = GetComponent<Text>();
    UpdateDisplay();
}

private void UpdateDisplay()
{
    starText.text = starText.ToString();
}

public void AddStars(int amount)
{
    stars = stars + amount;
    UpdateDisplay();

}

public bool HaveEnoughStars(int amount)
{
    return stars >= amount;

}

public void SpendStars(int amount)
{
    if (stars >= amount)
    {
        stars = stars - amount;
        UpdateDisplay();

    }
}

}

Someone gave
starText.text = stars.ToString();

and thought it might work. I still have the same error.

Hi Julian,

We do not provide support at the weekend, and I remember that I just replied in your thread on Udemy. Another student suggested a fix, you wrote you updated the code but I still see the original line of code in your code. Please do what the other student suggested. Then do what I suggested.


See also:

Yes I’ve done that. YOu can’t expect me to know when support is provided. If other students guessed it, good for them.

Could you please post your current code as formatted text?

Hi Nina,
Check carefully. 2 different files are in here. If you really got no time or cannot figure this out, I rather send this to the QA team so I don’t bother anyone.

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

public class StarDisplay : MonoBehaviour
{
[SerializeField] int stars = 100;
Text starText;

void Start()
{
    starText = GetComponent<Text>();
    UpdateDisplay();
}

private void UpdateDisplay()
{
    starText.text = stars.ToString();
}

public void AddStars(int amount)
{
    stars = stars + amount;
    UpdateDisplay();

}

public bool HaveEnoughStars(int amount)
{
    return stars >= amount;

}

public void SpendStars(int amount)
{
    if (stars >= amount)
    {
        stars = stars - amount;
        UpdateDisplay();

    }
}

}

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

public class Shooter : MonoBehaviour
{
[SerializeField] GameObject projectile, gun;
AttackerSpawner myLaneSpawner;

// Start is called before the first frame update
void Start()
{
    SetLaneSpawner();
}

// Update is called once per frame
private void Update()
{
    if (IsAttackerInLane())
    {
        Debug.Log("shoot pew pew");

    }

    else

    {
        Debug.Log("sit and wait");

    }

}

private void SetLaneSpawner()
{
    AttackerSpawner[] spawners = FindObjectsOfType<AttackerSpawner>();

    foreach (AttackerSpawner spawner in spawners)
    {
        bool IsCloseEnough = (Mathf.Abs(spawner.transform.position.y - transform.position.y) <= Mathf.Epsilon);

        if (IsCloseEnough)
        {
            myLaneSpawner = spawner;

        }
    }
}

private bool IsAttackerInLane()
{
    if (myLaneSpawner.transform.childCount <= 0)
    {
        return false;

    }

    else

    {
        return true;

    }
}

public void Fire()
{
    Instantiate(projectile, gun.transform.position, transform.rotation);

}

}

NullReferenceException means that a reference (“link”) to an instance is missing. Double click on the error message to see to which line in your code it is referring. If you exposed a field in the Inspector, make sure that it’s not empty. There must be a Text component assigned to the same game object as your StarDisplay instance.

Nina,
I have no idea what is the problem. I still don’t understand the difference between local & global variable. You might laugh or think stupidly of me but perhaps another better link can properly explain things to me. I will send this case to the unity QA team. I need the steps how to fix this. You gave the formula - which is useless as I don’t know how to apply the variables at this time. Sorry.

Log transform.localPosition into your console to get the local position. It’s the position you see in the Inspector of a game object. With transform.position, you get the global position.

ok. Put in which file / script?? Which position?

Check if the SetLaneSpawner method produces the desired result. Do that by using Debug.Logs to learn what’s going on there during runtime.

I got updates from the unity QA team. There are new codes and new items to insert into the game. I’ll update you when I get complete information. I removed the error but the points for trophy is still not counting.

Note: This is why I don’t like to depend too much on the tutorial. Suddenly, some new items are required and you never know.

It is generally a good idea not to rely too much on any tutorial because technology changes, so you cannot be 100% sure that everything will always work as seen in some tutorial. However, I don’t know what the Unity QA team implemented to fix your issues. From what I know, all other students didn’t have to implement any additional items to make this game work.

Hi Nina,
The results from the QA team is not good. It appears that it’s got something to do with the codes instead of the Unity app itself. I’ve checked the tutorial again and it should already work when i completed tutorial 149. I’ve checked my files and the codes look ok. I’m putting all my 3 files here so you can check for yourself. If you can’t figure this out, i’ll try again with the QA team. The files affected are Defender, StarDisplay, DefenderSpawner:

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

public class Defender : MonoBehaviour
{
    [SerializeField] int starCost = 100;
    
    public int GetStarCost()
    {
        return starCost;

    }



    public void AddStars(int amount)
    {
        FindObjectOfType<StarDisplay>().AddStars(amount);

    }
    
    
    /*
    void Start()
    {
        
    }

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


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

public class DefenderSpawner : MonoBehaviour
{
    Defender defender;

    private void OnMouseDown()
    {
        AttemptToPlaceDefenderAt(GetSquareClicked());
        //SpawnDefender();
    }

    public void SetSelectedDefender(Defender defenderToSelect)
    {
        defender = defenderToSelect;

    }

    private void AttemptToPlaceDefenderAt(Vector2 gridPos)
    {
        var StarDisplay = FindObjectOfType<StarDisplay>();
        int defenderCost = defender.GetStarCost();
        if (StarDisplay.HaveEnoughStars(defenderCost))
        {
            SpawnDefender(gridPos);
            StarDisplay.SpendStars(defenderCost);

        }

    }

    private Vector2 GetSquareClicked()
    {
        Vector2 clickPos = new Vector2(Input.mousePosition.x, Input.mousePosition.y);
        Vector2 worldPos = Camera.main.ScreenToWorldPoint(clickPos);
        Vector2 gridPos = SnapToGrid(worldPos);
        return gridPos;

    }

    private void AttemptToPlaceDefenderAt(Vector3 gridPos)
    {
        var StarDisplay = FindObjectOfType<StarDisplay>();
        int defenderCost = defender.GetStarCost();
        if (StarDisplay.HaveEnoughStars(defenderCost))
        {
            SpawnDefender(gridPos);
            StarDisplay.SpendStars(defenderCost);

        }

    }


    private Vector2 SnapToGrid(Vector2 rawWorldPos)
    {
        float newX = Mathf.RoundToInt(rawWorldPos.x);
        float newY = Mathf.RoundToInt(rawWorldPos.y);
        return new Vector2(newX, newY);
    }


    private void SpawnDefender(Vector2 roundedPos)
    {
        Defender newDefender = Instantiate(defender, roundedPos, Quaternion.identity) as Defender;
        Debug.Log(roundedPos);

    }

    /*
    void Start()
    {
        
    }

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

    */
}


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

public class StarDisplay : MonoBehaviour
{
    [SerializeField] int stars = 100;
    Text starText;

    void Start()
    {
        starText = GetComponent<Text>();
        UpdateDisplay();
    }

    private void UpdateDisplay()
    {
        starText.text = stars.ToString();
    }

    public void AddStars(int amount)
    {
        stars = stars + amount;
        UpdateDisplay();

    }

    public bool HaveEnoughStars(int amount)
    {
        return stars >= amount;

    }

    public void SpendStars(int amount)
    {
        if (stars >= amount)
        {
            stars = stars - amount;
            UpdateDisplay();

        }
    }
}

Have you already added Debug.Logs to your code? If so, what was the output in your console?

No I didn’t add. As an important update, I found the missing item - it was in prefab. But now, my trophy still doesn’t increment the count in points. My codes still remain the same. So now what can you suggest?

Check your console. Are there any error messages? If there aren’t any, add Debug.Logs to your code to see whether the trophy calls the method which increments the stars variable.

The error message i get seem to say that some rounding cannot be done. See this:

UnityEngine.Debug:Log(Object)
DefenderSpawner:SpawnDefender(Vector2) (at Assets/Scripts/DefenderSpawner.cs:68)
DefenderSpawner:AttemptToPlaceDefenderAt(Vector2) (at Assets/Scripts/DefenderSpawner.cs:27)
DefenderSpawner:OnMouseDown() (at Assets/Scripts/DefenderSpawner.cs:11)

AttemptToPlaceDefenderAt and SpawnDefender got called. What about the method where the stars get incremented?

Where do they count the points for the stars? Maybe i have it but didn’t see it. I only see the cactus and the trophy for now. Both are 100 points.

Check your classes and Inspector. Something is supposed to access the Star Display game object with the Text component.